<!DOCTYPE html>

<html>
<head>
  <title>SPE.js</title>
  <meta http-equiv="content-type" content="text/html; charset=UTF-8">
  <meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
  <link rel="stylesheet" media="all" href="docco.css" />
</head>
<body>
  <div id="container">
    <div id="background"></div>
    
    <ul class="sections">
        
          <li id="title">
              <div class="annotation">
                  <h1>SPE.js</h1>
              </div>
          </li>
        
        
        
        <li id="section-1">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-1">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-comment">/* shader-particle-engine 1.0.3
 * 
 * (c) 2015 Luke Moody (http://www.github.com/squarefeet)
 *     Originally based on Lee Stemkoski's original work (https://github.com/stemkoski/stemkoski.github.com/blob/master/Three.js/js/ParticleEngine.js).
 *
 * shader-particle-engine may be freely distributed under the MIT license (See LICENSE at root of this repository.)
 */</span>
<span class="hljs-comment">/**
 * @typedef {Number} distribution
 * @property {Number} SPE.distributions.BOX Values will be distributed within a box.
 * @property {Number} SPE.distributions.SPHERE Values will be distributed within a sphere.
 * @property {Number} SPE.distributions.DISC Values will be distributed within a 2D disc.
 */</span>

<span class="hljs-comment">/**
 * Namespace for Shader Particle Engine.
 *
 * All SPE-related code sits under this namespace.
 *
 * @type {Object}
 * @namespace
 */</span>
<span class="hljs-keyword">var</span> SPE = {

    <span class="hljs-comment">/**
     * A map of supported distribution types used
     * by SPE.Emitter instances.
     *
     * These distribution types can be applied to
     * an emitter globally, which will affect the
     * `position`, `velocity`, and `acceleration`
     * value calculations for an emitter, or they
     * can be applied on a per-property basis.
     *
     * @enum {Number}
     */</span>
    distributions: {
        <span class="hljs-comment">/**
         * Values will be distributed within a box.
         * @type {Number}
         */</span>
        BOX: <span class="hljs-number">1</span>,

        <span class="hljs-comment">/**
         * Values will be distributed on a sphere.
         * @type {Number}
         */</span>
        SPHERE: <span class="hljs-number">2</span>,

        <span class="hljs-comment">/**
         * Values will be distributed on a 2d-disc shape.
         * @type {Number}
         */</span>
        DISC: <span class="hljs-number">3</span>,
    },


    <span class="hljs-comment">/**
     * Set this value to however many 'steps' you
     * want value-over-lifetime properties to have.
     *
     * It's adjustable to fix an interpolation problem:
     *
     * Assuming you specify an opacity value as [0, 1, 0]
     *      and the `valueOverLifetimeLength` is 4, then the
     *      opacity value array will be reinterpolated to
     *      be [0, 0.66, 0.66, 0].
     *   This isn't ideal, as particles would never reach
     *   full opacity.
     *
     * <span class="hljs-doctag">NOTE:</span>
     *     This property affects the length of ALL
     *       value-over-lifetime properties for ALL
     *       emitters and ALL groups.
     *
     *     Only values &gt;= 3 &amp;&amp; &lt;= 4 are allowed.
     *
     * @type {Number}
     */</span>
    valueOverLifetimeLength: <span class="hljs-number">4</span>
};</pre></div></div>
            
        </li>
        
        
        <li id="section-2">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-2">&#182;</a>
              </div>
              <p>Module loader support:</p>

            </div>
            
            <div class="content"><div class='highlight'><pre><span class="hljs-keyword">if</span> ( <span class="hljs-keyword">typeof</span> define === <span class="hljs-string">'function'</span> &amp;&amp; define.amd ) {
    define( <span class="hljs-string">'spe'</span>, SPE );
}
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">typeof</span> exports !== <span class="hljs-string">'undefined'</span> &amp;&amp; <span class="hljs-keyword">typeof</span> <span class="hljs-built_in">module</span> !== <span class="hljs-string">'undefined'</span> ) {
    <span class="hljs-built_in">module</span>.exports = SPE;
}

<span class="hljs-comment">/**
 * A helper class for TypedArrays.
 *
 * Allows for easy resizing, assignment of various component-based
 * types (Vector2s, Vector3s, Vector4s, Mat3s, Mat4s),
 * as well as Colors (where components are `r`, `g`, `b`),
 * Numbers, and setting from other TypedArrays.
 *
 * @author Luke Moody
 * @constructor
 * @param {Function} TypedArrayConstructor The constructor to use (Float32Array, Uint8Array, etc.)
 * @param {Number} size                 The size of the array to create
 * @param {Number} componentSize        The number of components per-value (ie. 3 for a vec3, 9 for a Mat3, etc.)
 * @param {Number} indexOffset          The index in the array from which to start assigning values. Default `0` if none provided
 */</span>
SPE.TypedArrayHelper = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> TypedArrayConstructor, size, componentSize, indexOffset </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.componentSize = componentSize || <span class="hljs-number">1</span>;
    <span class="hljs-keyword">this</span>.size = ( size || <span class="hljs-number">1</span> );
    <span class="hljs-keyword">this</span>.TypedArrayConstructor = TypedArrayConstructor || <span class="hljs-built_in">Float32Array</span>;
    <span class="hljs-keyword">this</span>.array = <span class="hljs-keyword">new</span> TypedArrayConstructor( size * <span class="hljs-keyword">this</span>.componentSize );
    <span class="hljs-keyword">this</span>.indexOffset = indexOffset || <span class="hljs-number">0</span>;
};

SPE.TypedArrayHelper.constructor = SPE.TypedArrayHelper;

<span class="hljs-comment">/**
 * Sets the size of the internal array.
 *
 * Delegates to `this.shrink` or `this.grow` depending on size
 * argument's relation to the current size of the internal array.
 *
 * Note that if the array is to be shrunk, data will be lost.
 *
 * @param {Number} size The new size of the array.
 */</span>
SPE.TypedArrayHelper.prototype.setSize = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> size, noComponentMultiply </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> currentArraySize = <span class="hljs-keyword">this</span>.array.length;

    <span class="hljs-keyword">if</span> ( !noComponentMultiply ) {
        size = size * <span class="hljs-keyword">this</span>.componentSize;
    }

    <span class="hljs-keyword">if</span> ( size &lt; currentArraySize ) {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.shrink( size );
    }
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( size &gt; currentArraySize ) {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.grow( size );
    }
    <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">console</span>.info( <span class="hljs-string">'TypedArray is already of size:'</span>, size + <span class="hljs-string">'.'</span>, <span class="hljs-string">'Will not resize.'</span> );
    }
};

<span class="hljs-comment">/**
 * Shrinks the internal array.
 *
 * @param  {Number} size The new size of the typed array. Must be smaller than `this.array.length`.
 * @return {SPE.TypedArrayHelper}      Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.shrink = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> size </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.array = <span class="hljs-keyword">this</span>.array.subarray( <span class="hljs-number">0</span>, size );
    <span class="hljs-keyword">this</span>.size = size;
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};

<span class="hljs-comment">/**
 * Grows the internal array.
 * @param  {Number} size The new size of the typed array. Must be larger than `this.array.length`.
 * @return {SPE.TypedArrayHelper}      Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.grow = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> size </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> existingArray = <span class="hljs-keyword">this</span>.array,
        newArray = <span class="hljs-keyword">new</span> <span class="hljs-keyword">this</span>.TypedArrayConstructor( size );

    newArray.set( existingArray );
    <span class="hljs-keyword">this</span>.array = newArray;
    <span class="hljs-keyword">this</span>.size = size;

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};


<span class="hljs-comment">/**
 * Perform a splice operation on this array's buffer.
 * @param  {Number} start The start index of the splice. Will be multiplied by the number of components for this attribute.
 * @param  {Number} end The end index of the splice. Will be multiplied by the number of components for this attribute.
 * @returns {Object} The SPE.TypedArrayHelper instance.
 */</span>
SPE.TypedArrayHelper.prototype.splice = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> start, end </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;
    start *= <span class="hljs-keyword">this</span>.componentSize;
    end *= <span class="hljs-keyword">this</span>.componentSize;

    <span class="hljs-keyword">var</span> data = [],
        array = <span class="hljs-keyword">this</span>.array,
        size = array.length;

    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; size; ++i ) {
        <span class="hljs-keyword">if</span> ( i &lt; start || i &gt;= end ) {
            data.push( array[ i ] );
        }</pre></div></div>
            
        </li>
        
        
        <li id="section-3">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-3">&#182;</a>
              </div>
              <p>array[ i ] = 0;</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    }

    <span class="hljs-keyword">this</span>.setFromArray( <span class="hljs-number">0</span>, data );

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};


<span class="hljs-comment">/**
 * Copies from the given TypedArray into this one, using the index argument
 * as the start position. Alias for `TypedArray.set`. Will automatically resize
 * if the given source array is of a larger size than the internal array.
 *
 * @param {Number} index      The start position from which to copy into this array.
 * @param {TypedArray} array The array from which to copy; the source array.
 * @return {SPE.TypedArrayHelper} Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.setFromArray = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, array </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> sourceArraySize = array.length,
        newSize = index + sourceArraySize;

    <span class="hljs-keyword">if</span> ( newSize &gt; <span class="hljs-keyword">this</span>.array.length ) {
        <span class="hljs-keyword">this</span>.grow( newSize );
    }
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( newSize &lt; <span class="hljs-keyword">this</span>.array.length ) {
        <span class="hljs-keyword">this</span>.shrink( newSize );
    }

    <span class="hljs-keyword">this</span>.array.set( array, <span class="hljs-keyword">this</span>.indexOffset + index );

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};

<span class="hljs-comment">/**
 * Set a Vector2 value at `index`.
 *
 * @param {Number} index The index at which to set the vec2 values from.
 * @param {Vector2} vec2  Any object that has `x` and `y` properties.
 * @return {SPE.TypedArrayHelper} Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.setVec2 = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, vec2 </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.setVec2Components( index, vec2.x, vec2.y );
};

<span class="hljs-comment">/**
 * Set a Vector2 value using raw components.
 *
 * @param {Number} index The index at which to set the vec2 values from.
 * @param {Number} x     The Vec2's `x` component.
 * @param {Number} y     The Vec2's `y` component.
 * @return {SPE.TypedArrayHelper} Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.setVec2Components = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, x, y </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> array = <span class="hljs-keyword">this</span>.array,
        i = <span class="hljs-keyword">this</span>.indexOffset + ( index * <span class="hljs-keyword">this</span>.componentSize );

    array[ i ] = x;
    array[ i + <span class="hljs-number">1</span> ] = y;
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};

<span class="hljs-comment">/**
 * Set a Vector3 value at `index`.
 *
 * @param {Number} index The index at which to set the vec3 values from.
 * @param {Vector3} vec2  Any object that has `x`, `y`, and `z` properties.
 * @return {SPE.TypedArrayHelper} Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.setVec3 = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, vec3 </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.setVec3Components( index, vec3.x, vec3.y, vec3.z );
};

<span class="hljs-comment">/**
 * Set a Vector3 value using raw components.
 *
 * @param {Number} index The index at which to set the vec3 values from.
 * @param {Number} x     The Vec3's `x` component.
 * @param {Number} y     The Vec3's `y` component.
 * @param {Number} z     The Vec3's `z` component.
 * @return {SPE.TypedArrayHelper} Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.setVec3Components = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, x, y, z </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> array = <span class="hljs-keyword">this</span>.array,
        i = <span class="hljs-keyword">this</span>.indexOffset + ( index * <span class="hljs-keyword">this</span>.componentSize );

    array[ i ] = x;
    array[ i + <span class="hljs-number">1</span> ] = y;
    array[ i + <span class="hljs-number">2</span> ] = z;
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};

<span class="hljs-comment">/**
 * Set a Vector4 value at `index`.
 *
 * @param {Number} index The index at which to set the vec4 values from.
 * @param {Vector4} vec2  Any object that has `x`, `y`, `z`, and `w` properties.
 * @return {SPE.TypedArrayHelper} Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.setVec4 = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, vec4 </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.setVec4Components( index, vec4.x, vec4.y, vec4.z, vec4.w );
};

<span class="hljs-comment">/**
 * Set a Vector4 value using raw components.
 *
 * @param {Number} index The index at which to set the vec4 values from.
 * @param {Number} x     The Vec4's `x` component.
 * @param {Number} y     The Vec4's `y` component.
 * @param {Number} z     The Vec4's `z` component.
 * @param {Number} w     The Vec4's `w` component.
 * @return {SPE.TypedArrayHelper} Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.setVec4Components = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, x, y, z, w </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> array = <span class="hljs-keyword">this</span>.array,
        i = <span class="hljs-keyword">this</span>.indexOffset + ( index * <span class="hljs-keyword">this</span>.componentSize );

    array[ i ] = x;
    array[ i + <span class="hljs-number">1</span> ] = y;
    array[ i + <span class="hljs-number">2</span> ] = z;
    array[ i + <span class="hljs-number">3</span> ] = w;
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};

<span class="hljs-comment">/**
 * Set a Matrix3 value at `index`.
 *
 * @param {Number} index The index at which to set the matrix values from.
 * @param {Matrix3} mat3 The 3x3 matrix to set from. Must have a TypedArray property named `elements` to copy from.
 * @return {SPE.TypedArrayHelper} Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.setMat3 = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, mat3 </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.setFromArray( <span class="hljs-keyword">this</span>.indexOffset + ( index * <span class="hljs-keyword">this</span>.componentSize ), mat3.elements );
};

<span class="hljs-comment">/**
 * Set a Matrix4 value at `index`.
 *
 * @param {Number} index The index at which to set the matrix values from.
 * @param {Matrix4} mat3 The 4x4 matrix to set from. Must have a TypedArray property named `elements` to copy from.
 * @return {SPE.TypedArrayHelper} Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.setMat4 = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, mat4 </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.setFromArray( <span class="hljs-keyword">this</span>.indexOffset + ( index * <span class="hljs-keyword">this</span>.componentSize ), mat4.elements );
};

<span class="hljs-comment">/**
 * Set a Color value at `index`.
 *
 * @param {Number} index The index at which to set the vec3 values from.
 * @param {Color} color  Any object that has `r`, `g`, and `b` properties.
 * @return {SPE.TypedArrayHelper} Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.setColor = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, color </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.setVec3Components( index, color.r, color.g, color.b );
};

<span class="hljs-comment">/**
 * Set a Number value at `index`.
 *
 * @param {Number} index The index at which to set the vec3 values from.
 * @param {Number} numericValue  The number to assign to this index in the array.
 * @return {SPE.TypedArrayHelper} Instance of this class.
 */</span>
SPE.TypedArrayHelper.prototype.setNumber = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, numericValue </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.array[ <span class="hljs-keyword">this</span>.indexOffset + ( index * <span class="hljs-keyword">this</span>.componentSize ) ] = numericValue;
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};

<span class="hljs-comment">/**
 * Returns the value of the array at the given index, taking into account
 * the `indexOffset` property of this class.
 *
 * Note that this function ignores the component size and will just return a
 * single value.
 *
 * @param  {Number} index The index in the array to fetch.
 * @return {Number}       The value at the given index.
 */</span>
SPE.TypedArrayHelper.prototype.getValueAtIndex = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.array[ <span class="hljs-keyword">this</span>.indexOffset + index ];
};

<span class="hljs-comment">/**
 * Returns the component value of the array at the given index, taking into account
 * the `indexOffset` property of this class.
 *
 * If the componentSize is set to 3, then it will return a new TypedArray
 * of length 3.
 *
 * @param  {Number} index The index in the array to fetch.
 * @return {TypedArray}       The component value at the given index.
 */</span>
SPE.TypedArrayHelper.prototype.getComponentValueAtIndex = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.array.subarray( <span class="hljs-keyword">this</span>.indexOffset + ( index * <span class="hljs-keyword">this</span>.componentSize ) );
};

<span class="hljs-comment">/**
 * A helper to handle creating and updating a THREE.BufferAttribute instance.
 *
 * @author  Luke Moody
 * @constructor
 * @param {String} type          The buffer attribute type. See SPE.ShaderAttribute.typeSizeMap for valid values.
 * @param {Boolean=} dynamicBuffer Whether this buffer attribute should be marked as dynamic or not.
 * @param {Function=} arrayType     A reference to a TypedArray constructor. Defaults to Float32Array if none provided.
 */</span>
SPE.ShaderAttribute = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> type, dynamicBuffer, arrayType </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> typeMap = SPE.ShaderAttribute.typeSizeMap;

    <span class="hljs-keyword">this</span>.type = <span class="hljs-keyword">typeof</span> type === <span class="hljs-string">'string'</span> &amp;&amp; typeMap.hasOwnProperty( type ) ? type : <span class="hljs-string">'f'</span>;
    <span class="hljs-keyword">this</span>.componentSize = typeMap[ <span class="hljs-keyword">this</span>.type ];
    <span class="hljs-keyword">this</span>.arrayType = arrayType || <span class="hljs-built_in">Float32Array</span>;
    <span class="hljs-keyword">this</span>.typedArray = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">this</span>.bufferAttribute = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">this</span>.dynamicBuffer = !!dynamicBuffer;

    <span class="hljs-keyword">this</span>.updateMin = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">this</span>.updateMax = <span class="hljs-number">0</span>;
};

SPE.ShaderAttribute.constructor = SPE.ShaderAttribute;

<span class="hljs-comment">/**
 * A map of uniform types to their component size.
 * @enum {Number}
 */</span>
SPE.ShaderAttribute.typeSizeMap = {
    <span class="hljs-comment">/**
     * Float
     * @type {Number}
     */</span>
    f: <span class="hljs-number">1</span>,

    <span class="hljs-comment">/**
     * Vec2
     * @type {Number}
     */</span>
    v2: <span class="hljs-number">2</span>,

    <span class="hljs-comment">/**
     * Vec3
     * @type {Number}
     */</span>
    v3: <span class="hljs-number">3</span>,

    <span class="hljs-comment">/**
     * Vec4
     * @type {Number}
     */</span>
    v4: <span class="hljs-number">4</span>,

    <span class="hljs-comment">/**
     * Color
     * @type {Number}
     */</span>
    c: <span class="hljs-number">3</span>,

    <span class="hljs-comment">/**
     * Mat3
     * @type {Number}
     */</span>
    m3: <span class="hljs-number">9</span>,

    <span class="hljs-comment">/**
     * Mat4
     * @type {Number}
     */</span>
    m4: <span class="hljs-number">16</span>
};

<span class="hljs-comment">/**
 * Calculate the minimum and maximum update range for this buffer attribute using
 * component size independant min and max values.
 *
 * @param {Number} min The start of the range to mark as needing an update.
 * @param {Number} max The end of the range to mark as needing an update.
 */</span>
SPE.ShaderAttribute.prototype.setUpdateRange = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> min, max </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.updateMin = <span class="hljs-built_in">Math</span>.min( min * <span class="hljs-keyword">this</span>.componentSize, <span class="hljs-keyword">this</span>.updateMin * <span class="hljs-keyword">this</span>.componentSize );
    <span class="hljs-keyword">this</span>.updateMax = <span class="hljs-built_in">Math</span>.max( max * <span class="hljs-keyword">this</span>.componentSize, <span class="hljs-keyword">this</span>.updateMax * <span class="hljs-keyword">this</span>.componentSize );
};

<span class="hljs-comment">/**
 * Calculate the number of indices that this attribute should mark as needing
 * updating. Also marks the attribute as needing an update.
 */</span>
SPE.ShaderAttribute.prototype.flagUpdate = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> attr = <span class="hljs-keyword">this</span>.bufferAttribute,
        range = attr.updateRange;

    range.offset = <span class="hljs-keyword">this</span>.updateMin;
    range.count = <span class="hljs-built_in">Math</span>.min( ( <span class="hljs-keyword">this</span>.updateMax - <span class="hljs-keyword">this</span>.updateMin ) + <span class="hljs-keyword">this</span>.componentSize, <span class="hljs-keyword">this</span>.typedArray.array.length );</pre></div></div>
            
        </li>
        
        
        <li id="section-4">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-4">&#182;</a>
              </div>
              <p>console.log( range.offset, range.count, this.typedArray.array.length );
console.log( ‘flagUpdate:’, range.offset, range.count );</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    attr.needsUpdate = <span class="hljs-literal">true</span>;
};



<span class="hljs-comment">/**
 * Reset the index update counts for this attribute
 */</span>
SPE.ShaderAttribute.prototype.resetUpdateRange = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.updateMin = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">this</span>.updateMax = <span class="hljs-number">0</span>;
};

SPE.ShaderAttribute.prototype.resetDynamic = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;
    <span class="hljs-keyword">this</span>.bufferAttribute.dynamic = <span class="hljs-keyword">this</span>.dynamicBuffer;
};

<span class="hljs-comment">/**
 * Perform a splice operation on this attribute's buffer.
 * @param  {Number} start The start index of the splice. Will be multiplied by the number of components for this attribute.
 * @param  {Number} end The end index of the splice. Will be multiplied by the number of components for this attribute.
 */</span>
SPE.ShaderAttribute.prototype.splice = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> start, end </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.typedArray.splice( start, end );</pre></div></div>
            
        </li>
        
        
        <li id="section-5">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-5">&#182;</a>
              </div>
              <p>Reset the reference to the attribute’s typed array
since it has probably changed.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.forceUpdateAll();
};

SPE.ShaderAttribute.prototype.forceUpdateAll = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.bufferAttribute.array = <span class="hljs-keyword">this</span>.typedArray.array;
    <span class="hljs-keyword">this</span>.bufferAttribute.updateRange.offset = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">this</span>.bufferAttribute.updateRange.count = -<span class="hljs-number">1</span>;
    <span class="hljs-keyword">this</span>.bufferAttribute.dynamic = <span class="hljs-literal">false</span>;
    <span class="hljs-keyword">this</span>.bufferAttribute.needsUpdate = <span class="hljs-literal">true</span>;
};

<span class="hljs-comment">/**
 * Make sure this attribute has a typed array associated with it.
 *
 * If it does, then it will ensure the typed array is of the correct size.
 *
 * If not, a new SPE.TypedArrayHelper instance will be created.
 *
 * @param  {Number} size The size of the typed array to create or update to.
 */</span>
SPE.ShaderAttribute.prototype._ensureTypedArray = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> size </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-6">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-6">&#182;</a>
              </div>
              <p>Condition that’s most likely to be true at the top: no change.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.typedArray !== <span class="hljs-literal">null</span> &amp;&amp; <span class="hljs-keyword">this</span>.typedArray.size === size * <span class="hljs-keyword">this</span>.componentSize ) {
        <span class="hljs-keyword">return</span>;
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-7">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-7">&#182;</a>
              </div>
              <p>Resize the array if we need to, telling the TypedArrayHelper to
ignore it’s component size when evaluating size.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.typedArray !== <span class="hljs-literal">null</span> &amp;&amp; <span class="hljs-keyword">this</span>.typedArray.size !== size ) {
        <span class="hljs-keyword">this</span>.typedArray.setSize( size );
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-8">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-8">&#182;</a>
              </div>
              <p>This condition should only occur once in an attribute’s lifecycle.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.typedArray === <span class="hljs-literal">null</span> ) {
        <span class="hljs-keyword">this</span>.typedArray = <span class="hljs-keyword">new</span> SPE.TypedArrayHelper( <span class="hljs-keyword">this</span>.arrayType, size, <span class="hljs-keyword">this</span>.componentSize );
    }
};


<span class="hljs-comment">/**
 * Creates a THREE.BufferAttribute instance if one doesn't exist already.
 *
 * Ensures a typed array is present by calling _ensureTypedArray() first.
 *
 * If a buffer attribute exists already, then it will be marked as needing an update.
 *
 * @param  {Number} size The size of the typed array to create if one doesn't exist, or resize existing array to.
 */</span>
SPE.ShaderAttribute.prototype._createBufferAttribute = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> size </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-9">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-9">&#182;</a>
              </div>
              <p>Make sure the typedArray is present and correct.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>._ensureTypedArray( size );</pre></div></div>
            
        </li>
        
        
        <li id="section-10">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-10">&#182;</a>
              </div>
              <p>Don’t create it if it already exists, but do
flag that it needs updating on the next render
cycle.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.bufferAttribute !== <span class="hljs-literal">null</span> ) {
        <span class="hljs-keyword">this</span>.bufferAttribute.array = <span class="hljs-keyword">this</span>.typedArray.array;
        <span class="hljs-keyword">this</span>.bufferAttribute.needsUpdate = <span class="hljs-literal">true</span>;
        <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">this</span>.bufferAttribute = <span class="hljs-keyword">new</span> THREE.BufferAttribute( <span class="hljs-keyword">this</span>.typedArray.array, <span class="hljs-keyword">this</span>.componentSize );
    <span class="hljs-keyword">this</span>.bufferAttribute.dynamic = <span class="hljs-keyword">this</span>.dynamicBuffer;
};

<span class="hljs-comment">/**
 * Returns the length of the typed array associated with this attribute.
 * @return {Number} The length of the typed array. Will be 0 if no typed array has been created yet.
 */</span>
SPE.ShaderAttribute.prototype.getLength = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.typedArray === <span class="hljs-literal">null</span> ) {
        <span class="hljs-keyword">return</span> <span class="hljs-number">0</span>;
    }

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.typedArray.array.length;
};

SPE.shaderChunks = {</pre></div></div>
            
        </li>
        
        
        <li id="section-11">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-11">&#182;</a>
              </div>
              <p>Register color-packing define statements.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    defines: [
        <span class="hljs-string">'#define PACKED_COLOR_SIZE 256.0'</span>,
        <span class="hljs-string">'#define PACKED_COLOR_DIVISOR 255.0'</span>
    ].join( <span class="hljs-string">'\n'</span> ),</pre></div></div>
            
        </li>
        
        
        <li id="section-12">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-12">&#182;</a>
              </div>
              <p>All uniforms used by vertex / fragment shaders</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    uniforms: [
        <span class="hljs-string">'uniform float deltaTime;'</span>,
        <span class="hljs-string">'uniform float runTime;'</span>,
        <span class="hljs-string">'uniform sampler2D texture;'</span>,
        <span class="hljs-string">'uniform vec4 textureAnimation;'</span>,
        <span class="hljs-string">'uniform float scale;'</span>,
    ].join( <span class="hljs-string">'\n'</span> ),</pre></div></div>
            
        </li>
        
        
        <li id="section-13">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-13">&#182;</a>
              </div>
              <p>All attributes used by the vertex shader.</p>
<p>Note that some attributes are squashed into other ones:</p>
<ul>
<li>Drag is acceleration.w</li>
</ul>

            </div>
            
            <div class="content"><div class='highlight'><pre>    attributes: [
        <span class="hljs-string">'attribute vec4 acceleration;'</span>,
        <span class="hljs-string">'attribute vec3 velocity;'</span>,
        <span class="hljs-string">'attribute vec4 rotation;'</span>,
        <span class="hljs-string">'attribute vec3 rotationCenter;'</span>,
        <span class="hljs-string">'attribute vec4 params;'</span>,
        <span class="hljs-string">'attribute vec4 size;'</span>,
        <span class="hljs-string">'attribute vec4 angle;'</span>,
        <span class="hljs-string">'attribute vec4 color;'</span>,
        <span class="hljs-string">'attribute vec4 opacity;'</span>
    ].join( <span class="hljs-string">'\n'</span> ),</pre></div></div>
            
        </li>
        
        
        <li id="section-14">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-14">&#182;</a>
              </div>
              
            </div>
            
            <div class="content"><div class='highlight'><pre>    varyings: [
        <span class="hljs-string">'varying vec4 vColor;'</span>,
        <span class="hljs-string">'#ifdef SHOULD_ROTATE_TEXTURE'</span>,
        <span class="hljs-string">'    varying float vAngle;'</span>,
        <span class="hljs-string">'#endif'</span>,

        <span class="hljs-string">'#ifdef SHOULD_CALCULATE_SPRITE'</span>,
        <span class="hljs-string">'    varying vec4 vSpriteSheet;'</span>,
        <span class="hljs-string">'#endif'</span>
    ].join( <span class="hljs-string">'\n'</span> ),</pre></div></div>
            
        </li>
        
        
        <li id="section-15">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-15">&#182;</a>
              </div>
              <p>Branch-avoiding comparison fns</p>
<ul>
<li><a href="http://theorangeduck.com/page/avoiding-shader-conditionals">http://theorangeduck.com/page/avoiding-shader-conditionals</a></li>
</ul>

            </div>
            
            <div class="content"><div class='highlight'><pre>    branchAvoidanceFunctions: [
        <span class="hljs-string">'float when_gt(float x, float y) {'</span>,
        <span class="hljs-string">'    return max(sign(x - y), 0.0);'</span>,
        <span class="hljs-string">'}'</span>,

        <span class="hljs-string">'float when_lt(float x, float y) {'</span>,
        <span class="hljs-string">'    return min( max(1.0 - sign(x - y), 0.0), 1.0 );'</span>,
        <span class="hljs-string">'}'</span>,

        <span class="hljs-string">'float when_eq( float x, float y ) {'</span>,
        <span class="hljs-string">'    return 1.0 - abs( sign( x - y ) );'</span>,
        <span class="hljs-string">'}'</span>,

        <span class="hljs-string">'float when_ge(float x, float y) {'</span>,
        <span class="hljs-string">'  return 1.0 - when_lt(x, y);'</span>,
        <span class="hljs-string">'}'</span>,

        <span class="hljs-string">'float when_le(float x, float y) {'</span>,
        <span class="hljs-string">'  return 1.0 - when_gt(x, y);'</span>,
        <span class="hljs-string">'}'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-16">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-16">&#182;</a>
              </div>
              <p>Branch-avoiding logical operators
(to be used with above comparison fns)</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'float and(float a, float b) {'</span>,
        <span class="hljs-string">'    return a * b;'</span>,
        <span class="hljs-string">'}'</span>,

        <span class="hljs-string">'float or(float a, float b) {'</span>,
        <span class="hljs-string">'    return min(a + b, 1.0);'</span>,
        <span class="hljs-string">'}'</span>,
    ].join( <span class="hljs-string">'\n'</span> ),</pre></div></div>
            
        </li>
        
        
        <li id="section-17">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-17">&#182;</a>
              </div>
              <p>From:</p>
<ul>
<li><a href="http://stackoverflow.com/a/12553149">http://stackoverflow.com/a/12553149</a></li>
<li><a href="https://stackoverflow.com/questions/22895237/hexadecimal-to-rgb-values-in-webgl-shader">https://stackoverflow.com/questions/22895237/hexadecimal-to-rgb-values-in-webgl-shader</a></li>
</ul>

            </div>
            
            <div class="content"><div class='highlight'><pre>    unpackColor: [
        <span class="hljs-string">'vec3 unpackColor( in float hex ) {'</span>,
        <span class="hljs-string">'   vec3 c = vec3( 0.0 );'</span>,

        <span class="hljs-string">'   float r = mod( (hex / PACKED_COLOR_SIZE / PACKED_COLOR_SIZE), PACKED_COLOR_SIZE );'</span>,
        <span class="hljs-string">'   float g = mod( (hex / PACKED_COLOR_SIZE), PACKED_COLOR_SIZE );'</span>,
        <span class="hljs-string">'   float b = mod( hex, PACKED_COLOR_SIZE );'</span>,

        <span class="hljs-string">'   c.r = r / PACKED_COLOR_DIVISOR;'</span>,
        <span class="hljs-string">'   c.g = g / PACKED_COLOR_DIVISOR;'</span>,
        <span class="hljs-string">'   c.b = b / PACKED_COLOR_DIVISOR;'</span>,

        <span class="hljs-string">'   return c;'</span>,
        <span class="hljs-string">'}'</span>,
    ].join( <span class="hljs-string">'\n'</span> ),

    unpackRotationAxis: [
        <span class="hljs-string">'vec3 unpackRotationAxis( in float hex ) {'</span>,
        <span class="hljs-string">'   vec3 c = vec3( 0.0 );'</span>,

        <span class="hljs-string">'   float r = mod( (hex / PACKED_COLOR_SIZE / PACKED_COLOR_SIZE), PACKED_COLOR_SIZE );'</span>,
        <span class="hljs-string">'   float g = mod( (hex / PACKED_COLOR_SIZE), PACKED_COLOR_SIZE );'</span>,
        <span class="hljs-string">'   float b = mod( hex, PACKED_COLOR_SIZE );'</span>,

        <span class="hljs-string">'   c.r = r / PACKED_COLOR_DIVISOR;'</span>,
        <span class="hljs-string">'   c.g = g / PACKED_COLOR_DIVISOR;'</span>,
        <span class="hljs-string">'   c.b = b / PACKED_COLOR_DIVISOR;'</span>,

        <span class="hljs-string">'   c *= vec3( 2.0 );'</span>,
        <span class="hljs-string">'   c -= vec3( 1.0 );'</span>,

        <span class="hljs-string">'   return c;'</span>,
        <span class="hljs-string">'}'</span>,
    ].join( <span class="hljs-string">'\n'</span> ),

    floatOverLifetime: [
        <span class="hljs-string">'float getFloatOverLifetime( in float positionInTime, in vec4 attr ) {'</span>,
        <span class="hljs-string">'    highp float value = 0.0;'</span>,
        <span class="hljs-string">'    float deltaAge = positionInTime * float( VALUE_OVER_LIFETIME_LENGTH - 1 );'</span>,
        <span class="hljs-string">'    float fIndex = 0.0;'</span>,
        <span class="hljs-string">'    float shouldApplyValue = 0.0;'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-18">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-18">&#182;</a>
              </div>
              <p>This might look a little odd, but it’s faster in the testing I’ve done than using branches.
Uses basic maths to avoid branching.</p>
<p>Take a look at the branch-avoidance functions defined above,
and be sure to check out The Orange Duck site where I got this
from (link above).</p>

            </div>
            
        </li>
        
        
        <li id="section-19">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-19">&#182;</a>
              </div>
              <p>Fix for static emitters (age is always zero).</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    value += attr[ 0 ] * when_eq( deltaAge, 0.0 );'</span>,
        <span class="hljs-string">''</span>,
        <span class="hljs-string">'    for( int i = 0; i &lt; VALUE_OVER_LIFETIME_LENGTH - 1; ++i ) {'</span>,
        <span class="hljs-string">'       fIndex = float( i );'</span>,
        <span class="hljs-string">'       shouldApplyValue = and( when_gt( deltaAge, fIndex ), when_le( deltaAge, fIndex + 1.0 ) );'</span>,
        <span class="hljs-string">'       value += shouldApplyValue * mix( attr[ i ], attr[ i + 1 ], deltaAge - fIndex );'</span>,
        <span class="hljs-string">'    }'</span>,
        <span class="hljs-string">''</span>,
        <span class="hljs-string">'    return value;'</span>,
        <span class="hljs-string">'}'</span>,
    ].join( <span class="hljs-string">'\n'</span> ),

    colorOverLifetime: [
        <span class="hljs-string">'vec3 getColorOverLifetime( in float positionInTime, in vec3 color1, in vec3 color2, in vec3 color3, in vec3 color4 ) {'</span>,
        <span class="hljs-string">'    vec3 value = vec3( 0.0 );'</span>,
        <span class="hljs-string">'    value.x = getFloatOverLifetime( positionInTime, vec4( color1.x, color2.x, color3.x, color4.x ) );'</span>,
        <span class="hljs-string">'    value.y = getFloatOverLifetime( positionInTime, vec4( color1.y, color2.y, color3.y, color4.y ) );'</span>,
        <span class="hljs-string">'    value.z = getFloatOverLifetime( positionInTime, vec4( color1.z, color2.z, color3.z, color4.z ) );'</span>,
        <span class="hljs-string">'    return value;'</span>,
        <span class="hljs-string">'}'</span>,
    ].join( <span class="hljs-string">'\n'</span> ),

    paramFetchingFunctions: [
        <span class="hljs-string">'float getAlive() {'</span>,
        <span class="hljs-string">'   return params.x;'</span>,
        <span class="hljs-string">'}'</span>,

        <span class="hljs-string">'float getAge() {'</span>,
        <span class="hljs-string">'   return params.y;'</span>,
        <span class="hljs-string">'}'</span>,

        <span class="hljs-string">'float getMaxAge() {'</span>,
        <span class="hljs-string">'   return params.z;'</span>,
        <span class="hljs-string">'}'</span>,

        <span class="hljs-string">'float getWiggle() {'</span>,
        <span class="hljs-string">'   return params.w;'</span>,
        <span class="hljs-string">'}'</span>,
    ].join( <span class="hljs-string">'\n'</span> ),

    forceFetchingFunctions: [
        <span class="hljs-string">'vec4 getPosition( in float age ) {'</span>,
        <span class="hljs-string">'   return modelViewMatrix * vec4( position, 1.0 );'</span>,
        <span class="hljs-string">'}'</span>,

        <span class="hljs-string">'vec3 getVelocity( in float age ) {'</span>,
        <span class="hljs-string">'   return velocity * age;'</span>,
        <span class="hljs-string">'}'</span>,

        <span class="hljs-string">'vec3 getAcceleration( in float age ) {'</span>,
        <span class="hljs-string">'   return acceleration.xyz * age;'</span>,
        <span class="hljs-string">'}'</span>,
    ].join( <span class="hljs-string">'\n'</span> ),


    rotationFunctions: [</pre></div></div>
            
        </li>
        
        
        <li id="section-20">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-20">&#182;</a>
              </div>
              <p>Huge thanks to:</p>
<ul>
<li><a href="http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/">http://www.neilmendoza.com/glsl-rotation-about-an-arbitrary-axis/</a></li>
</ul>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'#ifdef SHOULD_ROTATE_PARTICLES'</span>,
        <span class="hljs-string">'   mat4 getRotationMatrix( in vec3 axis, in float angle) {'</span>,
        <span class="hljs-string">'       axis = normalize(axis);'</span>,
        <span class="hljs-string">'       float s = sin(angle);'</span>,
        <span class="hljs-string">'       float c = cos(angle);'</span>,
        <span class="hljs-string">'       float oc = 1.0 - c;'</span>,
        <span class="hljs-string">''</span>,
        <span class="hljs-string">'       return mat4(oc * axis.x * axis.x + c,           oc * axis.x * axis.y - axis.z * s,  oc * axis.z * axis.x + axis.y * s,  0.0,'</span>,
        <span class="hljs-string">'                   oc * axis.x * axis.y + axis.z * s,  oc * axis.y * axis.y + c,           oc * axis.y * axis.z - axis.x * s,  0.0,'</span>,
        <span class="hljs-string">'                   oc * axis.z * axis.x - axis.y * s,  oc * axis.y * axis.z + axis.x * s,  oc * axis.z * axis.z + c,           0.0,'</span>,
        <span class="hljs-string">'                   0.0,                                0.0,                                0.0,                                1.0);'</span>,
        <span class="hljs-string">'   }'</span>,
        <span class="hljs-string">''</span>,
        <span class="hljs-string">'   vec3 getRotation( in vec3 pos, in float positionInTime ) {'</span>,
        <span class="hljs-string">'      if( rotation.y == 0.0 ) {'</span>,
        <span class="hljs-string">'           return pos;'</span>,
        <span class="hljs-string">'      }'</span>,
        <span class="hljs-string">''</span>,
        <span class="hljs-string">'      vec3 axis = unpackRotationAxis( rotation.x );'</span>,
        <span class="hljs-string">'      vec3 center = rotationCenter;'</span>,
        <span class="hljs-string">'      vec3 translated;'</span>,
        <span class="hljs-string">'      mat4 rotationMatrix;'</span>,

        <span class="hljs-string">'      float angle = 0.0;'</span>,
        <span class="hljs-string">'      angle += when_eq( rotation.z, 0.0 ) * rotation.y;'</span>,
        <span class="hljs-string">'      angle += when_gt( rotation.z, 0.0 ) * mix( 0.0, rotation.y, positionInTime );'</span>,
        <span class="hljs-string">'      translated = rotationCenter - pos;'</span>,
        <span class="hljs-string">'      rotationMatrix = getRotationMatrix( axis, angle );'</span>,
        <span class="hljs-string">'      return center - vec3( rotationMatrix * vec4( translated, 0.0 ) );'</span>,
        <span class="hljs-string">'   }'</span>,
        <span class="hljs-string">'#endif'</span>
    ].join( <span class="hljs-string">'\n'</span> ),</pre></div></div>
            
        </li>
        
        
        <li id="section-21">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-21">&#182;</a>
              </div>
              <p>Fragment chunks</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    rotateTexture: [
        <span class="hljs-string">'    vec2 vUv = vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y );'</span>,
        <span class="hljs-string">''</span>,
        <span class="hljs-string">'    #ifdef SHOULD_ROTATE_TEXTURE'</span>,
        <span class="hljs-string">'       float x = gl_PointCoord.x - 0.5;'</span>,
        <span class="hljs-string">'       float y = 1.0 - gl_PointCoord.y - 0.5;'</span>,
        <span class="hljs-string">'       float c = cos( -vAngle );'</span>,
        <span class="hljs-string">'       float s = sin( -vAngle );'</span>,

        <span class="hljs-string">'       vUv = vec2( c * x + s * y + 0.5, c * y - s * x + 0.5 );'</span>,
        <span class="hljs-string">'    #endif'</span>,
        <span class="hljs-string">''</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-22">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-22">&#182;</a>
              </div>
              <p>Spritesheets overwrite angle calculations.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    #ifdef SHOULD_CALCULATE_SPRITE'</span>,
        <span class="hljs-string">'        float framesX = vSpriteSheet.x;'</span>,
        <span class="hljs-string">'        float framesY = vSpriteSheet.y;'</span>,
        <span class="hljs-string">'        float columnNorm = vSpriteSheet.z;'</span>,
        <span class="hljs-string">'        float rowNorm = vSpriteSheet.w;'</span>,

        <span class="hljs-string">'        vUv.x = gl_PointCoord.x * framesX + columnNorm;'</span>,
        <span class="hljs-string">'        vUv.y = 1.0 - (gl_PointCoord.y * framesY + rowNorm);'</span>,
        <span class="hljs-string">'    #endif'</span>,

        <span class="hljs-string">''</span>,
        <span class="hljs-string">'    vec4 rotatedTexture = texture2D( texture, vUv );'</span>,
    ].join( <span class="hljs-string">'\n'</span> )
};

SPE.shaders = {
    vertex: [
        SPE.shaderChunks.defines,
        SPE.shaderChunks.uniforms,
        SPE.shaderChunks.attributes,
        SPE.shaderChunks.varyings,

        THREE.ShaderChunk.common,
        THREE.ShaderChunk.logdepthbuf_pars_vertex,

        SPE.shaderChunks.branchAvoidanceFunctions,
        SPE.shaderChunks.unpackColor,
        SPE.shaderChunks.unpackRotationAxis,
        SPE.shaderChunks.floatOverLifetime,
        SPE.shaderChunks.colorOverLifetime,
        SPE.shaderChunks.paramFetchingFunctions,
        SPE.shaderChunks.forceFetchingFunctions,
        SPE.shaderChunks.rotationFunctions,


        <span class="hljs-string">'void main() {'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-23">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-23">&#182;</a>
              </div>
              <p>Setup…</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    highp float age = getAge();'</span>,
        <span class="hljs-string">'    highp float alive = getAlive();'</span>,
        <span class="hljs-string">'    highp float maxAge = getMaxAge();'</span>,
        <span class="hljs-string">'    highp float positionInTime = (age / maxAge);'</span>,
        <span class="hljs-string">'    highp float isAlive = when_gt( alive, 0.0 );'</span>,

        <span class="hljs-string">'    #ifdef SHOULD_WIGGLE_PARTICLES'</span>,
        <span class="hljs-string">'        float wiggleAmount = positionInTime * getWiggle();'</span>,
        <span class="hljs-string">'        float wiggleSin = isAlive * sin( wiggleAmount );'</span>,
        <span class="hljs-string">'        float wiggleCos = isAlive * cos( wiggleAmount );'</span>,
        <span class="hljs-string">'    #endif'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-24">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-24">&#182;</a>
              </div>
              <p>Forces</p>

            </div>
            
        </li>
        
        
        <li id="section-25">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-25">&#182;</a>
              </div>
              <p>Get forces &amp; position</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    vec3 vel = getVelocity( age );'</span>,
        <span class="hljs-string">'    vec3 accel = getAcceleration( age );'</span>,
        <span class="hljs-string">'    vec3 force = vec3( 0.0 );'</span>,
        <span class="hljs-string">'    vec3 pos = vec3( position );'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-26">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-26">&#182;</a>
              </div>
              <p>Calculate the required drag to apply to the forces.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    float drag = 1.0 - (positionInTime * 0.5) * acceleration.w;'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-27">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-27">&#182;</a>
              </div>
              <p>Integrate forces…</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    force += vel;'</span>,
        <span class="hljs-string">'    force *= drag;'</span>,
        <span class="hljs-string">'    force += accel * age;'</span>,
        <span class="hljs-string">'    pos += force;'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-28">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-28">&#182;</a>
              </div>
              <p>Wiggly wiggly wiggle!</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    #ifdef SHOULD_WIGGLE_PARTICLES'</span>,
        <span class="hljs-string">'        pos.x += wiggleSin;'</span>,
        <span class="hljs-string">'        pos.y += wiggleCos;'</span>,
        <span class="hljs-string">'        pos.z += wiggleSin;'</span>,
        <span class="hljs-string">'    #endif'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-29">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-29">&#182;</a>
              </div>
              <p>Rotate the emitter around it’s central point</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    #ifdef SHOULD_ROTATE_PARTICLES'</span>,
        <span class="hljs-string">'        pos = getRotation( pos, positionInTime );'</span>,
        <span class="hljs-string">'    #endif'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-30">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-30">&#182;</a>
              </div>
              <p>Convert pos to a world-space value</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    vec4 mvPos = modelViewMatrix * vec4( pos, 1.0 );'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-31">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-31">&#182;</a>
              </div>
              <p>Determine point size.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    highp float pointSize = getFloatOverLifetime( positionInTime, size ) * isAlive;'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-32">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-32">&#182;</a>
              </div>
              <p>Determine perspective</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    #ifdef HAS_PERSPECTIVE'</span>,
        <span class="hljs-string">'        float perspective = scale / length( mvPos.xyz );'</span>,
        <span class="hljs-string">'    #else'</span>,
        <span class="hljs-string">'        float perspective = 1.0;'</span>,
        <span class="hljs-string">'    #endif'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-33">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-33">&#182;</a>
              </div>
              <p>Apply perpective to pointSize value</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    float pointSizePerspective = pointSize * perspective;'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-34">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-34">&#182;</a>
              </div>
              <p>Appearance</p>

            </div>
            
        </li>
        
        
        <li id="section-35">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-35">&#182;</a>
              </div>
              <p>Determine color and opacity for this particle</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    #ifdef COLORIZE'</span>,
        <span class="hljs-string">'       vec3 c = isAlive * getColorOverLifetime('</span>,
        <span class="hljs-string">'           positionInTime,'</span>,
        <span class="hljs-string">'           unpackColor( color.x ),'</span>,
        <span class="hljs-string">'           unpackColor( color.y ),'</span>,
        <span class="hljs-string">'           unpackColor( color.z ),'</span>,
        <span class="hljs-string">'           unpackColor( color.w )'</span>,
        <span class="hljs-string">'       );'</span>,
        <span class="hljs-string">'    #else'</span>,
        <span class="hljs-string">'       vec3 c = vec3(1.0);'</span>,
        <span class="hljs-string">'    #endif'</span>,

        <span class="hljs-string">'    float o = isAlive * getFloatOverLifetime( positionInTime, opacity );'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-36">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-36">&#182;</a>
              </div>
              <p>Assign color to vColor varying.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    vColor = vec4( c, o );'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-37">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-37">&#182;</a>
              </div>
              <p>Determine angle</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    #ifdef SHOULD_ROTATE_TEXTURE'</span>,
        <span class="hljs-string">'        vAngle = isAlive * getFloatOverLifetime( positionInTime, angle );'</span>,
        <span class="hljs-string">'    #endif'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-38">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-38">&#182;</a>
              </div>
              <p>If this particle is using a sprite-sheet as a texture, we’ll have to figure out
what frame of the texture the particle is using at it’s current position in time.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    #ifdef SHOULD_CALCULATE_SPRITE'</span>,
        <span class="hljs-string">'        float framesX = textureAnimation.x;'</span>,
        <span class="hljs-string">'        float framesY = textureAnimation.y;'</span>,
        <span class="hljs-string">'        float loopCount = textureAnimation.w;'</span>,
        <span class="hljs-string">'        float totalFrames = textureAnimation.z;'</span>,
        <span class="hljs-string">'        float frameNumber = mod( (positionInTime * loopCount) * totalFrames, totalFrames );'</span>,

        <span class="hljs-string">'        float column = floor(mod( frameNumber, framesX ));'</span>,
        <span class="hljs-string">'        float row = floor( (frameNumber - column) / framesX );'</span>,

        <span class="hljs-string">'        float columnNorm = column / framesX;'</span>,
        <span class="hljs-string">'        float rowNorm = row / framesY;'</span>,

        <span class="hljs-string">'        vSpriteSheet.x = 1.0 / framesX;'</span>,
        <span class="hljs-string">'        vSpriteSheet.y = 1.0 / framesY;'</span>,
        <span class="hljs-string">'        vSpriteSheet.z = columnNorm;'</span>,
        <span class="hljs-string">'        vSpriteSheet.w = rowNorm;'</span>,
        <span class="hljs-string">'    #endif'</span>,</pre></div></div>
            
        </li>
        
        
        <li id="section-39">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-39">&#182;</a>
              </div>
              <p>Write values</p>

            </div>
            
        </li>
        
        
        <li id="section-40">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-40">&#182;</a>
              </div>
              <p>Set PointSize according to size at current point in time.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-string">'    gl_PointSize = pointSizePerspective;'</span>,
        <span class="hljs-string">'    gl_Position = projectionMatrix * mvPos;'</span>,

        THREE.ShaderChunk.logdepthbuf_vertex,

        <span class="hljs-string">'}'</span>
    ].join( <span class="hljs-string">'\n'</span> ),

    fragment: [
        SPE.shaderChunks.uniforms,

        THREE.ShaderChunk.common,
        THREE.ShaderChunk.fog_pars_fragment,
        THREE.ShaderChunk.logdepthbuf_pars_fragment,

        SPE.shaderChunks.varyings,

        SPE.shaderChunks.branchAvoidanceFunctions,

        <span class="hljs-string">'void main() {'</span>,
        <span class="hljs-string">'    vec3 outgoingLight = vColor.xyz;'</span>,
        <span class="hljs-string">'    '</span>,
        <span class="hljs-string">'    #ifdef ALPHATEST'</span>,
        <span class="hljs-string">'       if ( vColor.w &lt; float(ALPHATEST) ) discard;'</span>,
        <span class="hljs-string">'    #endif'</span>,

        SPE.shaderChunks.rotateTexture,

        THREE.ShaderChunk.logdepthbuf_fragment,

        <span class="hljs-string">'    outgoingLight = vColor.xyz * rotatedTexture.xyz;'</span>,

        THREE.ShaderChunk.fog_fragment,

        <span class="hljs-string">'    gl_FragColor = vec4( outgoingLight.xyz, rotatedTexture.w * vColor.w );'</span>,
        <span class="hljs-string">'}'</span>
    ].join( <span class="hljs-string">'\n'</span> )
};

<span class="hljs-comment">/**
 * A bunch of utility functions used throughout the library.
 * @namespace
 * @type {Object}
 */</span>
SPE.utils = {
    <span class="hljs-comment">/**
     * A map of types used by `SPE.utils.ensureTypedArg` and
     * `SPE.utils.ensureArrayTypedArg` to compare types against.
     *
     * @enum {String}
     */</span>
    types: {
        <span class="hljs-comment">/**
         * Boolean type.
         * @type {String}
         */</span>
        BOOLEAN: <span class="hljs-string">'boolean'</span>,

        <span class="hljs-comment">/**
         * String type.
         * @type {String}
         */</span>
        STRING: <span class="hljs-string">'string'</span>,

        <span class="hljs-comment">/**
         * Number type.
         * @type {String}
         */</span>
        NUMBER: <span class="hljs-string">'number'</span>,

        <span class="hljs-comment">/**
         * Object type.
         * @type {String}
         */</span>
        OBJECT: <span class="hljs-string">'object'</span>
    },

    <span class="hljs-comment">/**
     * Given a value, a type, and a default value to fallback to,
     * ensure the given argument adheres to the type requesting,
     * returning the default value if type check is false.
     *
     * @param  {(boolean|string|number|object)} arg          The value to perform a type-check on.
     * @param  {String} type         The type the `arg` argument should adhere to.
     * @param  {(boolean|string|number|object)} defaultValue A default value to fallback on if the type check fails.
     * @return {(boolean|string|number|object)}              The given value if type check passes, or the default value if it fails.
     */</span>
    ensureTypedArg: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> arg, type, defaultValue </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">typeof</span> arg === type ) {
            <span class="hljs-keyword">return</span> arg;
        }
        <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> defaultValue;
        }
    },

    <span class="hljs-comment">/**
     * Given an array of values, a type, and a default value,
     * ensure the given array's contents ALL adhere to the provided type,
     * returning the default value if type check fails.
     *
     * If the given value to check isn't an Array, delegates to SPE.utils.ensureTypedArg.
     *
     * @param  {Array|boolean|string|number|object} arg          The array of values to check type of.
     * @param  {String} type         The type that should be adhered to.
     * @param  {(boolean|string|number|object)} defaultValue A default fallback value.
     * @return {(boolean|string|number|object)}              The given value if type check passes, or the default value if it fails.
     */</span>
    ensureArrayTypedArg: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> arg, type, defaultValue </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-41">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-41">&#182;</a>
              </div>
              <p>If the argument being checked is an array, loop through
it and ensure all the values are of the correct type,
falling back to the defaultValue if any aren’t.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">if</span> ( <span class="hljs-built_in">Array</span>.isArray( arg ) ) {
            <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = arg.length - <span class="hljs-number">1</span>; i &gt;= <span class="hljs-number">0</span>; --i ) {
                <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">typeof</span> arg[ i ] !== type ) {
                    <span class="hljs-keyword">return</span> defaultValue;
                }
            }

            <span class="hljs-keyword">return</span> arg;
        }</pre></div></div>
            
        </li>
        
        
        <li id="section-42">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-42">&#182;</a>
              </div>
              <p>If the arg isn’t an array then just fallback to
checking the type.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.ensureTypedArg( arg, type, defaultValue );
    },

    <span class="hljs-comment">/**
     * Ensures the given value is an instance of a constructor function.
     *
     * @param  {Object} arg          The value to check instance of.
     * @param  {Function} instance     The constructor of the instance to check against.
     * @param  {Object} defaultValue A default fallback value if instance check fails
     * @return {Object}              The given value if type check passes, or the default value if it fails.
     */</span>
    ensureInstanceOf: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> arg, instance, defaultValue </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">if</span> ( instance !== <span class="hljs-literal">undefined</span> &amp;&amp; arg <span class="hljs-keyword">instanceof</span> instance ) {
            <span class="hljs-keyword">return</span> arg;
        }
        <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">return</span> defaultValue;
        }
    },

    <span class="hljs-comment">/**
     * Given an array of values, ensure the instances of all items in the array
     * matches the given instance constructor falling back to a default value if
     * the check fails.
     *
     * If given value isn't an Array, delegates to `SPE.utils.ensureInstanceOf`.
     *
     * @param  {Array|Object} arg          The value to perform the instanceof check on.
     * @param  {Function} instance     The constructor of the instance to check against.
     * @param  {Object} defaultValue A default fallback value if instance check fails
     * @return {Object}              The given value if type check passes, or the default value if it fails.
     */</span>
    ensureArrayInstanceOf: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> arg, instance, defaultValue </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-43">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-43">&#182;</a>
              </div>
              <p>If the argument being checked is an array, loop through
it and ensure all the values are of the correct type,
falling back to the defaultValue if any aren’t.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">if</span> ( <span class="hljs-built_in">Array</span>.isArray( arg ) ) {
            <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = arg.length - <span class="hljs-number">1</span>; i &gt;= <span class="hljs-number">0</span>; --i ) {
                <span class="hljs-keyword">if</span> ( instance !== <span class="hljs-literal">undefined</span> &amp;&amp; arg[ i ] <span class="hljs-keyword">instanceof</span> instance === <span class="hljs-literal">false</span> ) {
                    <span class="hljs-keyword">return</span> defaultValue;
                }
            }

            <span class="hljs-keyword">return</span> arg;
        }</pre></div></div>
            
        </li>
        
        
        <li id="section-44">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-44">&#182;</a>
              </div>
              <p>If the arg isn’t an array then just fallback to
checking the type.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.ensureInstanceOf( arg, instance, defaultValue );
    },

    <span class="hljs-comment">/**
     * Ensures that any "value-over-lifetime" properties of an emitter are
     * of the correct length (as dictated by `SPE.valueOverLifetimeLength`).
     *
     * Delegates to `SPE.utils.interpolateArray` for array resizing.
     *
     * If properties aren't arrays, then property values are put into one.
     *
     * @param  {Object} property  The property of an SPE.Emitter instance to check compliance of.
     * @param  {Number} minLength The minimum length of the array to create.
     * @param  {Number} maxLength The maximum length of the array to create.
     */</span>
    ensureValueOverLifetimeCompliance: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> property, minLength, maxLength </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        minLength = minLength || <span class="hljs-number">3</span>;
        maxLength = maxLength || <span class="hljs-number">3</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-45">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-45">&#182;</a>
              </div>
              <p>First, ensure both properties are arrays.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">if</span> ( <span class="hljs-built_in">Array</span>.isArray( property._value ) === <span class="hljs-literal">false</span> ) {
            property._value = [ property._value ];
        }

        <span class="hljs-keyword">if</span> ( <span class="hljs-built_in">Array</span>.isArray( property._spread ) === <span class="hljs-literal">false</span> ) {
            property._spread = [ property._spread ];
        }

        <span class="hljs-keyword">var</span> valueLength = <span class="hljs-keyword">this</span>.clamp( property._value.length, minLength, maxLength ),
            spreadLength = <span class="hljs-keyword">this</span>.clamp( property._spread.length, minLength, maxLength ),
            desiredLength = <span class="hljs-built_in">Math</span>.max( valueLength, spreadLength );

        <span class="hljs-keyword">if</span> ( property._value.length !== desiredLength ) {
            property._value = <span class="hljs-keyword">this</span>.interpolateArray( property._value, desiredLength );
        }

        <span class="hljs-keyword">if</span> ( property._spread.length !== desiredLength ) {
            property._spread = <span class="hljs-keyword">this</span>.interpolateArray( property._spread, desiredLength );
        }
    },

    <span class="hljs-comment">/**
     * Performs linear interpolation (lerp) on an array.
     *
     * For example, lerping [1, 10], with a `newLength` of 10 will produce [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].
     *
     * Delegates to `SPE.utils.lerpTypeAgnostic` to perform the actual
     * interpolation.
     *
     * @param  {Array} srcArray  The array to lerp.
     * @param  {Number} newLength The length the array should be interpolated to.
     * @return {Array}           The interpolated array.
     */</span>
    interpolateArray: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> srcArray, newLength </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">var</span> sourceLength = srcArray.length,
            newArray = [ <span class="hljs-keyword">typeof</span> srcArray[ <span class="hljs-number">0</span> ].clone === <span class="hljs-string">'function'</span> ? srcArray[ <span class="hljs-number">0</span> ].clone() : srcArray[ <span class="hljs-number">0</span> ] ],
            factor = ( sourceLength - <span class="hljs-number">1</span> ) / ( newLength - <span class="hljs-number">1</span> );


        <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = <span class="hljs-number">1</span>; i &lt; newLength - <span class="hljs-number">1</span>; ++i ) {
            <span class="hljs-keyword">var</span> f = i * factor,
                before = <span class="hljs-built_in">Math</span>.floor( f ),
                after = <span class="hljs-built_in">Math</span>.ceil( f ),
                delta = f - before;

            newArray[ i ] = <span class="hljs-keyword">this</span>.lerpTypeAgnostic( srcArray[ before ], srcArray[ after ], delta );
        }

        newArray.push(
            <span class="hljs-keyword">typeof</span> srcArray[ sourceLength - <span class="hljs-number">1</span> ].clone === <span class="hljs-string">'function'</span> ?
            srcArray[ sourceLength - <span class="hljs-number">1</span> ].clone() :
            srcArray[ sourceLength - <span class="hljs-number">1</span> ]
        );

        <span class="hljs-keyword">return</span> newArray;
    },

    <span class="hljs-comment">/**
     * Clamp a number to between the given min and max values.
     * @param  {Number} value The number to clamp.
     * @param  {Number} min   The minimum value.
     * @param  {Number} max   The maximum value.
     * @return {Number}       The clamped number.
     */</span>
    clamp: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> value, min, max </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">return</span> <span class="hljs-built_in">Math</span>.max( min, <span class="hljs-built_in">Math</span>.min( value, max ) );
    },

    <span class="hljs-comment">/**
     * If the given value is less than the epsilon value, then return
     * a randomised epsilon value if specified, or just the epsilon value if not.
     * Works for negative numbers as well as positive.
     *
     * @param  {Number} value     The value to perform the operation on.
     * @param  {Boolean} randomise Whether the value should be randomised.
     * @return {Number}           The result of the operation.
     */</span>
    zeroToEpsilon: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> value, randomise </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">var</span> epsilon = <span class="hljs-number">0.00001</span>,
            result = value;

        result = randomise ? <span class="hljs-built_in">Math</span>.random() * epsilon * <span class="hljs-number">10</span> : epsilon;

        <span class="hljs-keyword">if</span> ( value &lt; <span class="hljs-number">0</span> &amp;&amp; value &gt; -epsilon ) {
            result = -result;
        }</pre></div></div>
            
        </li>
        
        
        <li id="section-46">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-46">&#182;</a>
              </div>
              <p>if ( value === 0 ) {
    result = randomise ? Math.random() <em> epsilon </em> 10 : epsilon;
}
else if ( value &gt; 0 &amp;&amp; value &lt; epsilon ) {
    result = randomise ? Math.random() <em> epsilon </em> 10 : epsilon;
}
else if ( value &lt; 0 &amp;&amp; value &gt; -epsilon ) {
    result = -( randomise ? Math.random() <em> epsilon </em> 10 : epsilon );
}</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>
        <span class="hljs-keyword">return</span> result;
    },

    <span class="hljs-comment">/**
     * Linearly interpolates two values of various types. The given values
     * must be of the same type for the interpolation to work.
     * @param  {(number|Object)} start The start value of the lerp.
     * @param  {(number|object)} end   The end value of the lerp.
     * @param  {Number} delta The delta posiiton of the lerp operation. Ideally between 0 and 1 (inclusive).
     * @return {(number|object|undefined)}       The result of the operation. Result will be undefined if
     *                                               the start and end arguments aren't a supported type, or
     *                                               if their types do not match.
     */</span>
    lerpTypeAgnostic: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> start, end, delta </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">var</span> types = <span class="hljs-keyword">this</span>.types,
            out;

        <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">typeof</span> start === types.NUMBER &amp;&amp; <span class="hljs-keyword">typeof</span> end === types.NUMBER ) {
            <span class="hljs-keyword">return</span> start + ( ( end - start ) * delta );
        }
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( start <span class="hljs-keyword">instanceof</span> THREE.Vector2 &amp;&amp; end <span class="hljs-keyword">instanceof</span> THREE.Vector2 ) {
            out = start.clone();
            out.x = <span class="hljs-keyword">this</span>.lerp( start.x, end.x, delta );
            out.y = <span class="hljs-keyword">this</span>.lerp( start.y, end.y, delta );
            <span class="hljs-keyword">return</span> out;
        }
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( start <span class="hljs-keyword">instanceof</span> THREE.Vector3 &amp;&amp; end <span class="hljs-keyword">instanceof</span> THREE.Vector3 ) {
            out = start.clone();
            out.x = <span class="hljs-keyword">this</span>.lerp( start.x, end.x, delta );
            out.y = <span class="hljs-keyword">this</span>.lerp( start.y, end.y, delta );
            out.z = <span class="hljs-keyword">this</span>.lerp( start.z, end.z, delta );
            <span class="hljs-keyword">return</span> out;
        }
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( start <span class="hljs-keyword">instanceof</span> THREE.Vector4 &amp;&amp; end <span class="hljs-keyword">instanceof</span> THREE.Vector4 ) {
            out = start.clone();
            out.x = <span class="hljs-keyword">this</span>.lerp( start.x, end.x, delta );
            out.y = <span class="hljs-keyword">this</span>.lerp( start.y, end.y, delta );
            out.z = <span class="hljs-keyword">this</span>.lerp( start.z, end.z, delta );
            out.w = <span class="hljs-keyword">this</span>.lerp( start.w, end.w, delta );
            <span class="hljs-keyword">return</span> out;
        }
        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( start <span class="hljs-keyword">instanceof</span> THREE.Color &amp;&amp; end <span class="hljs-keyword">instanceof</span> THREE.Color ) {
            out = start.clone();
            out.r = <span class="hljs-keyword">this</span>.lerp( start.r, end.r, delta );
            out.g = <span class="hljs-keyword">this</span>.lerp( start.g, end.g, delta );
            out.b = <span class="hljs-keyword">this</span>.lerp( start.b, end.b, delta );
            <span class="hljs-keyword">return</span> out;
        }
        <span class="hljs-keyword">else</span> {
            <span class="hljs-built_in">console</span>.warn( <span class="hljs-string">'Invalid argument types, or argument types do not match:'</span>, start, end );
        }
    },

    <span class="hljs-comment">/**
     * Perform a linear interpolation operation on two numbers.
     * @param  {Number} start The start value.
     * @param  {Number} end   The end value.
     * @param  {Number} delta The position to interpolate to.
     * @return {Number}       The result of the lerp operation.
     */</span>
    lerp: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> start, end, delta </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;
        <span class="hljs-keyword">return</span> start + ( ( end - start ) * delta );
    },

    <span class="hljs-comment">/**
     * Rounds a number to a nearest multiple.
     *
     * @param  {Number} n        The number to round.
     * @param  {Number} multiple The multiple to round to.
     * @return {Number}          The result of the round operation.
     */</span>
    roundToNearestMultiple: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> n, multiple </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">var</span> remainder = <span class="hljs-number">0</span>;

        <span class="hljs-keyword">if</span> ( multiple === <span class="hljs-number">0</span> ) {
            <span class="hljs-keyword">return</span> n;
        }

        remainder = <span class="hljs-built_in">Math</span>.abs( n ) % multiple;

        <span class="hljs-keyword">if</span> ( remainder === <span class="hljs-number">0</span> ) {
            <span class="hljs-keyword">return</span> n;
        }

        <span class="hljs-keyword">if</span> ( n &lt; <span class="hljs-number">0</span> ) {
            <span class="hljs-keyword">return</span> -( <span class="hljs-built_in">Math</span>.abs( n ) - remainder );
        }

        <span class="hljs-keyword">return</span> n + multiple - remainder;
    },

    <span class="hljs-comment">/**
     * Check if all items in an array are equal. Uses strict equality.
     *
     * @param  {Array} array The array of values to check equality of.
     * @return {Boolean}       Whether the array's values are all equal or not.
     */</span>
    arrayValuesAreEqual: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> array </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; array.length - <span class="hljs-number">1</span>; ++i ) {
            <span class="hljs-keyword">if</span> ( array[ i ] !== array[ i + <span class="hljs-number">1</span> ] ) {
                <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
            }
        }

        <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
    },</pre></div></div>
            
        </li>
        
        
        <li id="section-47">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-47">&#182;</a>
              </div>
              <p>colorsAreEqual: function() {
    var colors = Array.prototype.slice.call( arguments ),
        numColors = colors.length;</p>

            </div>
            
        </li>
        
        
        <li id="section-48">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-48">&#182;</a>
              </div>
              <pre><code><span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>, color1, color2; i &lt; numColors - <span class="hljs-number">1</span>; ++i ) {
    color1 = colors[ i ];
    color2 = colors[ i + <span class="hljs-number">1</span> ];
</code></pre>
            </div>
            
        </li>
        
        
        <li id="section-49">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-49">&#182;</a>
              </div>
              <pre><code>    <span class="hljs-keyword">if</span> (
        color1.r !== color2.r ||
        color1.g !== color2.g ||
        color1.b !== color2.b
    ) {
        <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>
    }
}
</code></pre>
            </div>
            
        </li>
        
        
        <li id="section-50">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-50">&#182;</a>
              </div>
              <pre><code><span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
</code></pre><p>},</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>

    <span class="hljs-comment">/**
     * Given a start value and a spread value, create and return a random
     * number.
     * @param  {Number} base   The start value.
     * @param  {Number} spread The size of the random variance to apply.
     * @return {Number}        A randomised number.
     */</span>
    randomFloat: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> base, spread </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;
        <span class="hljs-keyword">return</span> base + spread * ( <span class="hljs-built_in">Math</span>.random() - <span class="hljs-number">0.5</span> );
    },



    <span class="hljs-comment">/**
     * Given an SPE.ShaderAttribute instance, and various other settings,
     * assign values to the attribute's array in a `vec3` format.
     *
     * @param  {Object} attribute   The instance of SPE.ShaderAttribute to save the result to.
     * @param  {Number} index       The offset in the attribute's TypedArray to save the result from.
     * @param  {Object} base        THREE.Vector3 instance describing the start value.
     * @param  {Object} spread      THREE.Vector3 instance describing the random variance to apply to the start value.
     * @param  {Object} spreadClamp THREE.Vector3 instance describing the multiples to clamp the randomness to.
     */</span>
    randomVector3: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> attribute, index, base, spread, spreadClamp </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">var</span> x = base.x + ( <span class="hljs-built_in">Math</span>.random() * spread.x - ( spread.x * <span class="hljs-number">0.5</span> ) ),
            y = base.y + ( <span class="hljs-built_in">Math</span>.random() * spread.y - ( spread.y * <span class="hljs-number">0.5</span> ) ),
            z = base.z + ( <span class="hljs-built_in">Math</span>.random() * spread.z - ( spread.z * <span class="hljs-number">0.5</span> ) );</pre></div></div>
            
        </li>
        
        
        <li id="section-51">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-51">&#182;</a>
              </div>
              <p>var x = this.randomFloat( base.x, spread.x ),
y = this.randomFloat( base.y, spread.y ),
z = this.randomFloat( base.z, spread.z );</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>
        <span class="hljs-keyword">if</span> ( spreadClamp ) {
            x = -spreadClamp.x * <span class="hljs-number">0.5</span> + <span class="hljs-keyword">this</span>.roundToNearestMultiple( x, spreadClamp.x );
            y = -spreadClamp.y * <span class="hljs-number">0.5</span> + <span class="hljs-keyword">this</span>.roundToNearestMultiple( y, spreadClamp.y );
            z = -spreadClamp.z * <span class="hljs-number">0.5</span> + <span class="hljs-keyword">this</span>.roundToNearestMultiple( z, spreadClamp.z );
        }

        attribute.typedArray.setVec3Components( index, x, y, z );
    },

    <span class="hljs-comment">/**
     * Given an SPE.Shader attribute instance, and various other settings,
     * assign Color values to the attribute.
     * @param  {Object} attribute The instance of SPE.ShaderAttribute to save the result to.
     * @param  {Number} index     The offset in the attribute's TypedArray to save the result from.
     * @param  {Object} base      THREE.Color instance describing the start color.
     * @param  {Object} spread    THREE.Vector3 instance describing the random variance to apply to the start color.
     */</span>
    randomColor: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> attribute, index, base, spread </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">var</span> r = base.r + ( <span class="hljs-built_in">Math</span>.random() * spread.x ),
            g = base.g + ( <span class="hljs-built_in">Math</span>.random() * spread.y ),
            b = base.b + ( <span class="hljs-built_in">Math</span>.random() * spread.z );

        r = <span class="hljs-keyword">this</span>.clamp( r, <span class="hljs-number">0</span>, <span class="hljs-number">1</span> );
        g = <span class="hljs-keyword">this</span>.clamp( g, <span class="hljs-number">0</span>, <span class="hljs-number">1</span> );
        b = <span class="hljs-keyword">this</span>.clamp( b, <span class="hljs-number">0</span>, <span class="hljs-number">1</span> );


        attribute.typedArray.setVec3Components( index, r, g, b );
    },


    randomColorAsHex: ( <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">var</span> workingColor = <span class="hljs-keyword">new</span> THREE.Color();

        <span class="hljs-comment">/**
         * Assigns a random color value, encoded as a hex value in decimal
         * format, to a SPE.ShaderAttribute instance.
         * @param  {Object} attribute The instance of SPE.ShaderAttribute to save the result to.
         * @param  {Number} index     The offset in the attribute's TypedArray to save the result from.
         * @param  {Object} base      THREE.Color instance describing the start color.
         * @param  {Object} spread    THREE.Vector3 instance describing the random variance to apply to the start color.
         */</span>
        <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> attribute, index, base, spread </span>) </span>{
            <span class="hljs-keyword">var</span> numItems = base.length,
                colors = [];

            <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; numItems; ++i ) {
                <span class="hljs-keyword">var</span> spreadVector = spread[ i ];

                workingColor.copy( base[ i ] );

                workingColor.r += ( <span class="hljs-built_in">Math</span>.random() * spreadVector.x ) - ( spreadVector.x * <span class="hljs-number">0.5</span> );
                workingColor.g += ( <span class="hljs-built_in">Math</span>.random() * spreadVector.y ) - ( spreadVector.y * <span class="hljs-number">0.5</span> );
                workingColor.b += ( <span class="hljs-built_in">Math</span>.random() * spreadVector.z ) - ( spreadVector.z * <span class="hljs-number">0.5</span> );

                workingColor.r = <span class="hljs-keyword">this</span>.clamp( workingColor.r, <span class="hljs-number">0</span>, <span class="hljs-number">1</span> );
                workingColor.g = <span class="hljs-keyword">this</span>.clamp( workingColor.g, <span class="hljs-number">0</span>, <span class="hljs-number">1</span> );
                workingColor.b = <span class="hljs-keyword">this</span>.clamp( workingColor.b, <span class="hljs-number">0</span>, <span class="hljs-number">1</span> );

                colors.push( workingColor.getHex() );
            }

            attribute.typedArray.setVec4Components( index, colors[ <span class="hljs-number">0</span> ], colors[ <span class="hljs-number">1</span> ], colors[ <span class="hljs-number">2</span> ], colors[ <span class="hljs-number">3</span> ] );
        };
    }() ),

    <span class="hljs-comment">/**
     * Assigns a random vector 3 value to an SPE.ShaderAttribute instance, projecting the
     * given values onto a sphere.
     *
     * @param  {Object} attribute The instance of SPE.ShaderAttribute to save the result to.
     * @param  {Number} index     The offset in the attribute's TypedArray to save the result from.
     * @param  {Object} base              THREE.Vector3 instance describing the origin of the transform.
     * @param  {Number} radius            The radius of the sphere to project onto.
     * @param  {Number} radiusSpread      The amount of randomness to apply to the projection result
     * @param  {Object} radiusScale       THREE.Vector3 instance describing the scale of each axis of the sphere.
     * @param  {Number} radiusSpreadClamp What numeric multiple the projected value should be clamped to.
     */</span>
    randomVector3OnSphere: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">
        attribute, index, base, radius, radiusSpread, radiusScale, radiusSpreadClamp, distributionClamp
    </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">var</span> depth = <span class="hljs-number">2</span> * <span class="hljs-built_in">Math</span>.random() - <span class="hljs-number">1</span>,
            t = <span class="hljs-number">6.2832</span> * <span class="hljs-built_in">Math</span>.random(),
            r = <span class="hljs-built_in">Math</span>.sqrt( <span class="hljs-number">1</span> - depth * depth ),
            rand = <span class="hljs-keyword">this</span>.randomFloat( radius, radiusSpread ),
            x = <span class="hljs-number">0</span>,
            y = <span class="hljs-number">0</span>,
            z = <span class="hljs-number">0</span>;


        <span class="hljs-keyword">if</span> ( radiusSpreadClamp ) {
            rand = <span class="hljs-built_in">Math</span>.round( rand / radiusSpreadClamp ) * radiusSpreadClamp;
        }</pre></div></div>
            
        </li>
        
        
        <li id="section-52">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-52">&#182;</a>
              </div>
              <p>Set position on sphere</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        x = r * <span class="hljs-built_in">Math</span>.cos( t ) * rand;
        y = r * <span class="hljs-built_in">Math</span>.sin( t ) * rand;
        z = depth * rand;</pre></div></div>
            
        </li>
        
        
        <li id="section-53">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-53">&#182;</a>
              </div>
              <p>Apply radius scale to this position</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        x *= radiusScale.x;
        y *= radiusScale.y;
        z *= radiusScale.z;</pre></div></div>
            
        </li>
        
        
        <li id="section-54">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-54">&#182;</a>
              </div>
              <p>Translate to the base position.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        x += base.x;
        y += base.y;
        z += base.z;</pre></div></div>
            
        </li>
        
        
        <li id="section-55">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-55">&#182;</a>
              </div>
              <p>Set the values in the typed array.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        attribute.typedArray.setVec3Components( index, x, y, z );
    },

    seededRandom: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> seed </span>) </span>{
        <span class="hljs-keyword">var</span> x = <span class="hljs-built_in">Math</span>.sin( seed ) * <span class="hljs-number">10000</span>;
        <span class="hljs-keyword">return</span> x - ( x | <span class="hljs-number">0</span> );
    },



    <span class="hljs-comment">/**
     * Assigns a random vector 3 value to an SPE.ShaderAttribute instance, projecting the
     * given values onto a 2d-disc.
     *
     * @param  {Object} attribute The instance of SPE.ShaderAttribute to save the result to.
     * @param  {Number} index     The offset in the attribute's TypedArray to save the result from.
     * @param  {Object} base              THREE.Vector3 instance describing the origin of the transform.
     * @param  {Number} radius            The radius of the sphere to project onto.
     * @param  {Number} radiusSpread      The amount of randomness to apply to the projection result
     * @param  {Object} radiusScale       THREE.Vector3 instance describing the scale of each axis of the disc. The z-component is ignored.
     * @param  {Number} radiusSpreadClamp What numeric multiple the projected value should be clamped to.
     */</span>
    randomVector3OnDisc: <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> attribute, index, base, radius, radiusSpread, radiusScale, radiusSpreadClamp </span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">var</span> t = <span class="hljs-number">6.2832</span> * <span class="hljs-built_in">Math</span>.random(),
            rand = <span class="hljs-built_in">Math</span>.abs( <span class="hljs-keyword">this</span>.randomFloat( radius, radiusSpread ) ),
            x = <span class="hljs-number">0</span>,
            y = <span class="hljs-number">0</span>,
            z = <span class="hljs-number">0</span>;

        <span class="hljs-keyword">if</span> ( radiusSpreadClamp ) {
            rand = <span class="hljs-built_in">Math</span>.round( rand / radiusSpreadClamp ) * radiusSpreadClamp;
        }</pre></div></div>
            
        </li>
        
        
        <li id="section-56">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-56">&#182;</a>
              </div>
              <p>Set position on sphere</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        x = <span class="hljs-built_in">Math</span>.cos( t ) * rand;
        y = <span class="hljs-built_in">Math</span>.sin( t ) * rand;</pre></div></div>
            
        </li>
        
        
        <li id="section-57">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-57">&#182;</a>
              </div>
              <p>Apply radius scale to this position</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        x *= radiusScale.x;
        y *= radiusScale.y;</pre></div></div>
            
        </li>
        
        
        <li id="section-58">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-58">&#182;</a>
              </div>
              <p>Translate to the base position.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        x += base.x;
        y += base.y;
        z += base.z;</pre></div></div>
            
        </li>
        
        
        <li id="section-59">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-59">&#182;</a>
              </div>
              <p>Set the values in the typed array.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        attribute.typedArray.setVec3Components( index, x, y, z );
    },

    randomDirectionVector3OnSphere: ( <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">var</span> v = <span class="hljs-keyword">new</span> THREE.Vector3();

        <span class="hljs-comment">/**
         * Given an SPE.ShaderAttribute instance, create a direction vector from the given
         * position, using `speed` as the magnitude. Values are saved to the attribute.
         *
         * @param  {Object} attribute       The instance of SPE.ShaderAttribute to save the result to.
         * @param  {Number} index           The offset in the attribute's TypedArray to save the result from.
         * @param  {Number} posX            The particle's x coordinate.
         * @param  {Number} posY            The particle's y coordinate.
         * @param  {Number} posZ            The particle's z coordinate.
         * @param  {Object} emitterPosition THREE.Vector3 instance describing the emitter's base position.
         * @param  {Number} speed           The magnitude to apply to the vector.
         * @param  {Number} speedSpread     The amount of randomness to apply to the magnitude.
         */</span>
        <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> attribute, index, posX, posY, posZ, emitterPosition, speed, speedSpread </span>) </span>{
            v.copy( emitterPosition );

            v.x -= posX;
            v.y -= posY;
            v.z -= posZ;

            v.normalize().multiplyScalar( -<span class="hljs-keyword">this</span>.randomFloat( speed, speedSpread ) );

            attribute.typedArray.setVec3Components( index, v.x, v.y, v.z );
        };
    }() ),


    randomDirectionVector3OnDisc: ( <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">var</span> v = <span class="hljs-keyword">new</span> THREE.Vector3();

        <span class="hljs-comment">/**
         * Given an SPE.ShaderAttribute instance, create a direction vector from the given
         * position, using `speed` as the magnitude. Values are saved to the attribute.
         *
         * @param  {Object} attribute       The instance of SPE.ShaderAttribute to save the result to.
         * @param  {Number} index           The offset in the attribute's TypedArray to save the result from.
         * @param  {Number} posX            The particle's x coordinate.
         * @param  {Number} posY            The particle's y coordinate.
         * @param  {Number} posZ            The particle's z coordinate.
         * @param  {Object} emitterPosition THREE.Vector3 instance describing the emitter's base position.
         * @param  {Number} speed           The magnitude to apply to the vector.
         * @param  {Number} speedSpread     The amount of randomness to apply to the magnitude.
         */</span>
        <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> attribute, index, posX, posY, posZ, emitterPosition, speed, speedSpread </span>) </span>{
            v.copy( emitterPosition );

            v.x -= posX;
            v.y -= posY;
            v.z -= posZ;

            v.normalize().multiplyScalar( -<span class="hljs-keyword">this</span>.randomFloat( speed, speedSpread ) );

            attribute.typedArray.setVec3Components( index, v.x, v.y, <span class="hljs-number">0</span> );
        };
    }() ),

    getPackedRotationAxis: ( <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">        'use strict'</span>;

        <span class="hljs-keyword">var</span> v = <span class="hljs-keyword">new</span> THREE.Vector3(),
            vSpread = <span class="hljs-keyword">new</span> THREE.Vector3(),
            c = <span class="hljs-keyword">new</span> THREE.Color(),
            addOne = <span class="hljs-keyword">new</span> THREE.Vector3( <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span> );

        <span class="hljs-comment">/**
         * Given a rotation axis, and a rotation axis spread vector,
         * calculate a randomised rotation axis, and pack it into
         * a hexadecimal value represented in decimal form.
         * @param  {Object} axis       THREE.Vector3 instance describing the rotation axis.
         * @param  {Object} axisSpread THREE.Vector3 instance describing the amount of randomness to apply to the rotation axis.
         * @return {Number}            The packed rotation axis, with randomness.
         */</span>
        <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> axis, axisSpread </span>) </span>{
            v.copy( axis ).normalize();
            vSpread.copy( axisSpread ).normalize();

            v.x += ( -axisSpread.x * <span class="hljs-number">0.5</span> ) + ( <span class="hljs-built_in">Math</span>.random() * axisSpread.x );
            v.y += ( -axisSpread.y * <span class="hljs-number">0.5</span> ) + ( <span class="hljs-built_in">Math</span>.random() * axisSpread.y );
            v.z += ( -axisSpread.z * <span class="hljs-number">0.5</span> ) + ( <span class="hljs-built_in">Math</span>.random() * axisSpread.z );</pre></div></div>
            
        </li>
        
        
        <li id="section-60">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-60">&#182;</a>
              </div>
              <p>v.x = Math.abs( v.x );
v.y = Math.abs( v.y );
v.z = Math.abs( v.z );</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>
            v.normalize().add( addOne ).multiplyScalar( <span class="hljs-number">0.5</span> );

            c.setRGB( v.x, v.y, v.z );

            <span class="hljs-keyword">return</span> c.getHex();
        };
    }() )
};

<span class="hljs-comment">/**
 * An SPE.Group instance.
 * @typedef {Object} Group
 * @see SPE.Group
 */</span>

<span class="hljs-comment">/**
 * A map of options to configure an SPE.Group instance.
 * @typedef {Object} GroupOptions
 *
 * @property {Object} texture An object describing the texture used by the group.
 *
 * @property {Object} texture.value An instance of THREE.Texture.
 *
 * @property {Object=} texture.frames A THREE.Vector2 instance describing the number
 *                                    of frames on the x- and y-axis of the given texture.
 *                                    If not provided, the texture will NOT be treated as
 *                                    a sprite-sheet and as such will NOT be animated.
 *
 * @property {Number} [texture.frameCount=texture.frames.x * texture.frames.y] The total number of frames in the sprite-sheet.
 *                                                                   Allows for sprite-sheets that don't fill the entire
 *                                                                   texture.
 *
 * @property {Number} texture.loop The number of loops through the sprite-sheet that should
 *                                 be performed over the course of a single particle's lifetime.
 *
 * @property {Number} fixedTimeStep If no `dt` (or `deltaTime`) value is passed to this group's
 *                                  `tick()` function, this number will be used to move the particle
 *                                  simulation forward. Value in SECONDS.
 *
 * @property {Boolean} hasPerspective Whether the distance a particle is from the camera should affect
 *                                    the particle's size.
 *
 * @property {Boolean} colorize Whether the particles in this group should be rendered with color, or
 *                              whether the only color of particles will come from the provided texture.
 *
 * @property {Number} blending One of Three.js's blending modes to apply to this group's `ShaderMaterial`.
 *
 * @property {Boolean} transparent Whether these particle's should be rendered with transparency.
 *
 * @property {Number} alphaTest Sets the alpha value to be used when running an alpha test on the `texture.value` property. Value between 0 and 1.
 *
 * @property {Boolean} depthWrite Whether rendering the group has any effect on the depth buffer.
 *
 * @property {Boolean} depthTest Whether to have depth test enabled when rendering this group.
 *
 * @property {Boolean} fog Whether this group's particles should be affected by their scene's fog.
 *
 * @property {Number} scale The scale factor to apply to this group's particle sizes. Useful for
 *                          setting particle sizes to be relative to renderer size.
 */</span>


<span class="hljs-comment">/**
 * The SPE.Group class. Creates a new group, containing a material, geometry, and mesh.
 *
 * @constructor
 * @param {GroupOptions} options A map of options to configure the group instance.
 */</span>
SPE.Group = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> options </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> utils = SPE.utils,
        types = utils.types;</pre></div></div>
            
        </li>
        
        
        <li id="section-61">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-61">&#182;</a>
              </div>
              <p>Ensure we have a map of options to play with</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    options = utils.ensureTypedArg( options, types.OBJECT, {} );
    options.texture = utils.ensureTypedArg( options.texture, types.OBJECT, {} );</pre></div></div>
            
        </li>
        
        
        <li id="section-62">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-62">&#182;</a>
              </div>
              <p>Assign a UUID to this instance</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.uuid = THREE.Math.generateUUID();</pre></div></div>
            
        </li>
        
        
        <li id="section-63">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-63">&#182;</a>
              </div>
              <p>If no <code>deltaTime</code> value is passed to the <code>SPE.Group.tick</code> function,
the value of this property will be used to advance the simulation.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.fixedTimeStep = utils.ensureTypedArg( options.fixedTimeStep, types.NUMBER, <span class="hljs-number">0.016</span> );</pre></div></div>
            
        </li>
        
        
        <li id="section-64">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-64">&#182;</a>
              </div>
              <p>Set properties used in the uniforms map, starting with the
texture stuff.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.texture = utils.ensureInstanceOf( options.texture.value, THREE.Texture, <span class="hljs-literal">null</span> );
    <span class="hljs-keyword">this</span>.textureFrames = utils.ensureInstanceOf( options.texture.frames, THREE.Vector2, <span class="hljs-keyword">new</span> THREE.Vector2( <span class="hljs-number">1</span>, <span class="hljs-number">1</span> ) );
    <span class="hljs-keyword">this</span>.textureFrameCount = utils.ensureTypedArg( options.texture.frameCount, types.NUMBER, <span class="hljs-keyword">this</span>.textureFrames.x * <span class="hljs-keyword">this</span>.textureFrames.y );
    <span class="hljs-keyword">this</span>.textureLoop = utils.ensureTypedArg( options.texture.loop, types.NUMBER, <span class="hljs-number">1</span> );
    <span class="hljs-keyword">this</span>.textureFrames.max( <span class="hljs-keyword">new</span> THREE.Vector2( <span class="hljs-number">1</span>, <span class="hljs-number">1</span> ) );

    <span class="hljs-keyword">this</span>.hasPerspective = utils.ensureTypedArg( options.hasPerspective, types.BOOLEAN, <span class="hljs-literal">true</span> );
    <span class="hljs-keyword">this</span>.colorize = utils.ensureTypedArg( options.colorize, types.BOOLEAN, <span class="hljs-literal">true</span> );

    <span class="hljs-keyword">this</span>.maxParticleCount = utils.ensureTypedArg( options.maxParticleCount, types.NUMBER, <span class="hljs-literal">null</span> );</pre></div></div>
            
        </li>
        
        
        <li id="section-65">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-65">&#182;</a>
              </div>
              <p>Set properties used to define the ShaderMaterial’s appearance.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.blending = utils.ensureTypedArg( options.blending, types.NUMBER, THREE.AdditiveBlending );
    <span class="hljs-keyword">this</span>.transparent = utils.ensureTypedArg( options.transparent, types.BOOLEAN, <span class="hljs-literal">true</span> );
    <span class="hljs-keyword">this</span>.alphaTest = <span class="hljs-built_in">parseFloat</span>( utils.ensureTypedArg( options.alphaTest, types.NUMBER, <span class="hljs-number">0.0</span> ) );
    <span class="hljs-keyword">this</span>.depthWrite = utils.ensureTypedArg( options.depthWrite, types.BOOLEAN, <span class="hljs-literal">false</span> );
    <span class="hljs-keyword">this</span>.depthTest = utils.ensureTypedArg( options.depthTest, types.BOOLEAN, <span class="hljs-literal">true</span> );
    <span class="hljs-keyword">this</span>.fog = utils.ensureTypedArg( options.fog, types.BOOLEAN, <span class="hljs-literal">true</span> );
    <span class="hljs-keyword">this</span>.scale = utils.ensureTypedArg( options.scale, types.NUMBER, <span class="hljs-number">300</span> );</pre></div></div>
            
        </li>
        
        
        <li id="section-66">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-66">&#182;</a>
              </div>
              <p>Where emitter’s go to curl up in a warm blanket and live
out their days.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.emitters = [];
    <span class="hljs-keyword">this</span>.emitterIDs = [];</pre></div></div>
            
        </li>
        
        
        <li id="section-67">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-67">&#182;</a>
              </div>
              <p>Create properties for use by the emitter pooling functions.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>._pool = [];
    <span class="hljs-keyword">this</span>._poolCreationSettings = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">this</span>._createNewWhenPoolEmpty = <span class="hljs-number">0</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-68">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-68">&#182;</a>
              </div>
              <p>Whether all attributes should be forced to updated
their entire buffer contents on the next tick.</p>
<p>Used when an emitter is removed.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>._attributesNeedRefresh = <span class="hljs-literal">false</span>;
    <span class="hljs-keyword">this</span>._attributesNeedDynamicReset = <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">this</span>.particleCount = <span class="hljs-number">0</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-69">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-69">&#182;</a>
              </div>
              <p>Map of uniforms to be applied to the ShaderMaterial instance.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.uniforms = {
        texture: {
            type: <span class="hljs-string">'t'</span>,
            value: <span class="hljs-keyword">this</span>.texture
        },
        textureAnimation: {
            type: <span class="hljs-string">'v4'</span>,
            value: <span class="hljs-keyword">new</span> THREE.Vector4(
                <span class="hljs-keyword">this</span>.textureFrames.x,
                <span class="hljs-keyword">this</span>.textureFrames.y,
                <span class="hljs-keyword">this</span>.textureFrameCount,
                <span class="hljs-built_in">Math</span>.max( <span class="hljs-built_in">Math</span>.abs( <span class="hljs-keyword">this</span>.textureLoop ), <span class="hljs-number">1.0</span> )
            )
        },
        fogColor: {
            type: <span class="hljs-string">'c'</span>,
            value: <span class="hljs-literal">null</span>
        },
        fogNear: {
            type: <span class="hljs-string">'f'</span>,
            value: <span class="hljs-number">10</span>
        },
        fogFar: {
            type: <span class="hljs-string">'f'</span>,
            value: <span class="hljs-number">200</span>
        },
        fogDensity: {
            type: <span class="hljs-string">'f'</span>,
            value: <span class="hljs-number">0.5</span>
        },
        deltaTime: {
            type: <span class="hljs-string">'f'</span>,
            value: <span class="hljs-number">0</span>
        },
        runTime: {
            type: <span class="hljs-string">'f'</span>,
            value: <span class="hljs-number">0</span>
        },
        scale: {
            type: <span class="hljs-string">'f'</span>,
            value: <span class="hljs-keyword">this</span>.scale
        }
    };</pre></div></div>
            
        </li>
        
        
        <li id="section-70">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-70">&#182;</a>
              </div>
              <p>Add some defines into the mix…</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.defines = {
        HAS_PERSPECTIVE: <span class="hljs-keyword">this</span>.hasPerspective,
        COLORIZE: <span class="hljs-keyword">this</span>.colorize,
        VALUE_OVER_LIFETIME_LENGTH: SPE.valueOverLifetimeLength,

        SHOULD_ROTATE_TEXTURE: <span class="hljs-literal">false</span>,
        SHOULD_ROTATE_PARTICLES: <span class="hljs-literal">false</span>,
        SHOULD_WIGGLE_PARTICLES: <span class="hljs-literal">false</span>,

        SHOULD_CALCULATE_SPRITE: <span class="hljs-keyword">this</span>.textureFrames.x &gt; <span class="hljs-number">1</span> || <span class="hljs-keyword">this</span>.textureFrames.y &gt; <span class="hljs-number">1</span>
    };</pre></div></div>
            
        </li>
        
        
        <li id="section-71">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-71">&#182;</a>
              </div>
              <p>Map of all attributes to be applied to the particles.</p>
<p>See SPE.ShaderAttribute for a bit more info on this bit.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.attributes = {
        position: <span class="hljs-keyword">new</span> SPE.ShaderAttribute( <span class="hljs-string">'v3'</span>, <span class="hljs-literal">true</span> ),
        acceleration: <span class="hljs-keyword">new</span> SPE.ShaderAttribute( <span class="hljs-string">'v4'</span>, <span class="hljs-literal">true</span> ), <span class="hljs-comment">// w component is drag</span>
        velocity: <span class="hljs-keyword">new</span> SPE.ShaderAttribute( <span class="hljs-string">'v3'</span>, <span class="hljs-literal">true</span> ),
        rotation: <span class="hljs-keyword">new</span> SPE.ShaderAttribute( <span class="hljs-string">'v4'</span>, <span class="hljs-literal">true</span> ),
        rotationCenter: <span class="hljs-keyword">new</span> SPE.ShaderAttribute( <span class="hljs-string">'v3'</span>, <span class="hljs-literal">true</span> ),
        params: <span class="hljs-keyword">new</span> SPE.ShaderAttribute( <span class="hljs-string">'v4'</span>, <span class="hljs-literal">true</span> ), <span class="hljs-comment">// Holds (alive, age, delay, wiggle)</span>
        size: <span class="hljs-keyword">new</span> SPE.ShaderAttribute( <span class="hljs-string">'v4'</span>, <span class="hljs-literal">true</span> ),
        angle: <span class="hljs-keyword">new</span> SPE.ShaderAttribute( <span class="hljs-string">'v4'</span>, <span class="hljs-literal">true</span> ),
        color: <span class="hljs-keyword">new</span> SPE.ShaderAttribute( <span class="hljs-string">'v4'</span>, <span class="hljs-literal">true</span> ),
        opacity: <span class="hljs-keyword">new</span> SPE.ShaderAttribute( <span class="hljs-string">'v4'</span>, <span class="hljs-literal">true</span> )
    };

    <span class="hljs-keyword">this</span>.attributeKeys = <span class="hljs-built_in">Object</span>.keys( <span class="hljs-keyword">this</span>.attributes );
    <span class="hljs-keyword">this</span>.attributeCount = <span class="hljs-keyword">this</span>.attributeKeys.length;</pre></div></div>
            
        </li>
        
        
        <li id="section-72">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-72">&#182;</a>
              </div>
              <p>Create the ShaderMaterial instance that’ll help render the
particles.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.material = <span class="hljs-keyword">new</span> THREE.ShaderMaterial( {
        uniforms: <span class="hljs-keyword">this</span>.uniforms,
        vertexShader: SPE.shaders.vertex,
        fragmentShader: SPE.shaders.fragment,
        blending: <span class="hljs-keyword">this</span>.blending,
        transparent: <span class="hljs-keyword">this</span>.transparent,
        alphaTest: <span class="hljs-keyword">this</span>.alphaTest,
        depthWrite: <span class="hljs-keyword">this</span>.depthWrite,
        depthTest: <span class="hljs-keyword">this</span>.depthTest,
        defines: <span class="hljs-keyword">this</span>.defines,
        fog: <span class="hljs-keyword">this</span>.fog
    } );</pre></div></div>
            
        </li>
        
        
        <li id="section-73">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-73">&#182;</a>
              </div>
              <p>Create the BufferGeometry and Points instances, ensuring
the geometry and material are given to the latter.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.geometry = <span class="hljs-keyword">new</span> THREE.BufferGeometry();
    <span class="hljs-keyword">this</span>.mesh = <span class="hljs-keyword">new</span> THREE.Points( <span class="hljs-keyword">this</span>.geometry, <span class="hljs-keyword">this</span>.material );

    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.maxParticleCount === <span class="hljs-literal">null</span> ) {
        <span class="hljs-built_in">console</span>.warn( <span class="hljs-string">'SPE.Group: No maxParticleCount specified. Adding emitters after rendering will probably cause errors.'</span> );
    }
};

SPE.Group.constructor = SPE.Group;


SPE.Group.prototype._updateDefines = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> emitters = <span class="hljs-keyword">this</span>.emitters,
        i = emitters.length - <span class="hljs-number">1</span>,
        emitter,
        defines = <span class="hljs-keyword">this</span>.defines;

    <span class="hljs-keyword">for</span> ( i; i &gt;= <span class="hljs-number">0</span>; --i ) {
        emitter = emitters[ i ];</pre></div></div>
            
        </li>
        
        
        <li id="section-74">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-74">&#182;</a>
              </div>
              <p>Only do angle calculation if there’s no spritesheet defined.</p>
<p>Saves calculations being done and then overwritten in the shaders.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">if</span> ( !defines.SHOULD_CALCULATE_SPRITE ) {
            defines.SHOULD_ROTATE_TEXTURE = defines.SHOULD_ROTATE_TEXTURE || !!<span class="hljs-built_in">Math</span>.max(
                <span class="hljs-built_in">Math</span>.max.apply( <span class="hljs-literal">null</span>, emitter.angle.value ),
                <span class="hljs-built_in">Math</span>.max.apply( <span class="hljs-literal">null</span>, emitter.angle.spread )
            );
        }

        defines.SHOULD_ROTATE_PARTICLES = defines.SHOULD_ROTATE_PARTICLES || !!<span class="hljs-built_in">Math</span>.max(
            emitter.rotation.angle,
            emitter.rotation.angleSpread
        );

        defines.SHOULD_WIGGLE_PARTICLES = defines.SHOULD_WIGGLE_PARTICLES || !!<span class="hljs-built_in">Math</span>.max(
            emitter.wiggle.value,
            emitter.wiggle.spread
        );
    }

    <span class="hljs-keyword">this</span>.material.needsUpdate = <span class="hljs-literal">true</span>;
};

SPE.Group.prototype._applyAttributesToGeometry = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> attributes = <span class="hljs-keyword">this</span>.attributes,
        geometry = <span class="hljs-keyword">this</span>.geometry,
        geometryAttributes = geometry.attributes,
        attribute,
        geometryAttribute;</pre></div></div>
            
        </li>
        
        
        <li id="section-75">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-75">&#182;</a>
              </div>
              <p>Loop through all the shader attributes and assign (or re-assign)
typed array buffers to each one.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> attr <span class="hljs-keyword">in</span> attributes ) {
        <span class="hljs-keyword">if</span> ( attributes.hasOwnProperty( attr ) ) {
            attribute = attributes[ attr ];
            geometryAttribute = geometryAttributes[ attr ];</pre></div></div>
            
        </li>
        
        
        <li id="section-76">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-76">&#182;</a>
              </div>
              <p>Update the array if this attribute exists on the geometry.</p>
<p>This needs to be done because the attribute’s typed array might have
been resized and reinstantiated, and might now be looking at a
different ArrayBuffer, so reference needs updating.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>            <span class="hljs-keyword">if</span> ( geometryAttribute ) {
                geometryAttribute.array = attribute.typedArray.array;
            }</pre></div></div>
            
        </li>
        
        
        <li id="section-77">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-77">&#182;</a>
              </div>
              <p>// Add the attribute to the geometry if it doesn’t already exist.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>            <span class="hljs-keyword">else</span> {
                geometry.addAttribute( attr, attribute.bufferAttribute );
            }</pre></div></div>
            
        </li>
        
        
        <li id="section-78">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-78">&#182;</a>
              </div>
              <p>Mark the attribute as needing an update the next time a frame is rendered.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>            attribute.bufferAttribute.needsUpdate = <span class="hljs-literal">true</span>;
        }
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-79">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-79">&#182;</a>
              </div>
              <p>Mark the draw range on the geometry. This will ensure
only the values in the attribute buffers that are
associated with a particle will be used in THREE’s
render cycle.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.geometry.setDrawRange( <span class="hljs-number">0</span>, <span class="hljs-keyword">this</span>.particleCount );
};

<span class="hljs-comment">/**
 * Adds an SPE.Emitter instance to this group, creating particle values and
 * assigning them to this group's shader attributes.
 *
 * @param {Emitter} emitter The emitter to add to this group.
 */</span>
SPE.Group.prototype.addEmitter = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> emitter </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-80">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-80">&#182;</a>
              </div>
              <p>Ensure an actual emitter instance is passed here.</p>
<p>Decided not to throw here, just in case a scene’s
rendering would be paused. Logging an error instead
of stopping execution if exceptions aren’t caught.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> ( emitter <span class="hljs-keyword">instanceof</span> SPE.Emitter === <span class="hljs-literal">false</span> ) {
        <span class="hljs-built_in">console</span>.error( <span class="hljs-string">'`emitter` argument must be instance of SPE.Emitter. Was provided with:'</span>, emitter );
        <span class="hljs-keyword">return</span>;
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-81">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-81">&#182;</a>
              </div>
              <p>If the emitter already exists as a member of this group, then
stop here, we don’t want to add it again.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.emitterIDs.indexOf( emitter.uuid ) &gt; -<span class="hljs-number">1</span> ) {
        <span class="hljs-built_in">console</span>.error( <span class="hljs-string">'Emitter already exists in this group. Will not add again.'</span> );
        <span class="hljs-keyword">return</span>;
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-82">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-82">&#182;</a>
              </div>
              <p>And finally, if the emitter is a member of another group,
don’t add it to this group.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( emitter.group !== <span class="hljs-literal">null</span> ) {
        <span class="hljs-built_in">console</span>.error( <span class="hljs-string">'Emitter already belongs to another group. Will not add to requested group.'</span> );
        <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">var</span> attributes = <span class="hljs-keyword">this</span>.attributes,
        start = <span class="hljs-keyword">this</span>.particleCount,
        end = start + emitter.particleCount;</pre></div></div>
            
        </li>
        
        
        <li id="section-83">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-83">&#182;</a>
              </div>
              <p>Update this group’s particle count.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.particleCount = end;</pre></div></div>
            
        </li>
        
        
        <li id="section-84">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-84">&#182;</a>
              </div>
              <p>Emit a warning if the emitter being added will exceed the buffer sizes specified.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.maxParticleCount !== <span class="hljs-literal">null</span> &amp;&amp; <span class="hljs-keyword">this</span>.particleCount &gt; <span class="hljs-keyword">this</span>.maxParticleCount ) {
        <span class="hljs-built_in">console</span>.warn( <span class="hljs-string">'SPE.Group: maxParticleCount exceeded. Requesting'</span>, <span class="hljs-keyword">this</span>.particleCount, <span class="hljs-string">'particles, can support only'</span>, <span class="hljs-keyword">this</span>.maxParticleCount );
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-85">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-85">&#182;</a>
              </div>
              <p>Set the <code>particlesPerSecond</code> value (PPS) on the emitter.
It’s used to determine how many particles to release
on a per-frame basis.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    emitter._calculatePPSValue( emitter.maxAge._value + emitter.maxAge._spread );
    emitter._setBufferUpdateRanges( <span class="hljs-keyword">this</span>.attributeKeys );</pre></div></div>
            
        </li>
        
        
        <li id="section-86">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-86">&#182;</a>
              </div>
              <p>Store the offset value in the TypedArray attributes for this emitter.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    emitter._setAttributeOffset( start );</pre></div></div>
            
        </li>
        
        
        <li id="section-87">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-87">&#182;</a>
              </div>
              <p>Save a reference to this group on the emitter so it knows
where it belongs.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    emitter.group = <span class="hljs-keyword">this</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-88">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-88">&#182;</a>
              </div>
              <p>Store reference to the attributes on the emitter for
easier access during the emitter’s tick function.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    emitter.attributes = <span class="hljs-keyword">this</span>.attributes;</pre></div></div>
            
        </li>
        
        
        <li id="section-89">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-89">&#182;</a>
              </div>
              <p>Ensure the attributes and their BufferAttributes exist, and their
TypedArrays are of the correct size.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> attr <span class="hljs-keyword">in</span> attributes ) {
        <span class="hljs-keyword">if</span> ( attributes.hasOwnProperty( attr ) ) {</pre></div></div>
            
        </li>
        
        
        <li id="section-90">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-90">&#182;</a>
              </div>
              <p>When creating a buffer, pass through the maxParticle count
if one is specified.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>            attributes[ attr ]._createBufferAttribute(
                <span class="hljs-keyword">this</span>.maxParticleCount !== <span class="hljs-literal">null</span> ?
                <span class="hljs-keyword">this</span>.maxParticleCount :
                <span class="hljs-keyword">this</span>.particleCount
            );
        }
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-91">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-91">&#182;</a>
              </div>
              <p>Loop through each particle this emitter wants to have, and create the attributes values,
storing them in the TypedArrays that each attribute holds.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = start; i &lt; end; ++i ) {
        emitter._assignPositionValue( i );
        emitter._assignForceValue( i, <span class="hljs-string">'velocity'</span> );
        emitter._assignForceValue( i, <span class="hljs-string">'acceleration'</span> );
        emitter._assignAbsLifetimeValue( i, <span class="hljs-string">'opacity'</span> );
        emitter._assignAbsLifetimeValue( i, <span class="hljs-string">'size'</span> );
        emitter._assignAngleValue( i );
        emitter._assignRotationValue( i );
        emitter._assignParamsValue( i );
        emitter._assignColorValue( i );
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-92">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-92">&#182;</a>
              </div>
              <p>Update the geometry and make sure the attributes are referencing
the typed arrays properly.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>._applyAttributesToGeometry();</pre></div></div>
            
        </li>
        
        
        <li id="section-93">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-93">&#182;</a>
              </div>
              <p>Store this emitter in this group’s emitter’s store.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.emitters.push( emitter );
    <span class="hljs-keyword">this</span>.emitterIDs.push( emitter.uuid );</pre></div></div>
            
        </li>
        
        
        <li id="section-94">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-94">&#182;</a>
              </div>
              <p>Update certain flags to enable shader calculations only if they’re necessary.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>._updateDefines( emitter );</pre></div></div>
            
        </li>
        
        
        <li id="section-95">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-95">&#182;</a>
              </div>
              <p>Update the material since defines might have changed</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.material.needsUpdate = <span class="hljs-literal">true</span>;
    <span class="hljs-keyword">this</span>.geometry.needsUpdate = <span class="hljs-literal">true</span>;
    <span class="hljs-keyword">this</span>._attributesNeedRefresh = <span class="hljs-literal">true</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-96">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-96">&#182;</a>
              </div>
              <p>Return the group to enable chaining.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};

<span class="hljs-comment">/**
 * Removes an SPE.Emitter instance from this group. When called,
 * all particle's belonging to the given emitter will be instantly
 * removed from the scene.
 *
 * @param {Emitter} emitter The emitter to add to this group.
 */</span>
SPE.Group.prototype.removeEmitter = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> emitter </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> emitterIndex = <span class="hljs-keyword">this</span>.emitterIDs.indexOf( emitter.uuid );</pre></div></div>
            
        </li>
        
        
        <li id="section-97">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-97">&#182;</a>
              </div>
              <p>Ensure an actual emitter instance is passed here.</p>
<p>Decided not to throw here, just in case a scene’s
rendering would be paused. Logging an error instead
of stopping execution if exceptions aren’t caught.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> ( emitter <span class="hljs-keyword">instanceof</span> SPE.Emitter === <span class="hljs-literal">false</span> ) {
        <span class="hljs-built_in">console</span>.error( <span class="hljs-string">'`emitter` argument must be instance of SPE.Emitter. Was provided with:'</span>, emitter );
        <span class="hljs-keyword">return</span>;
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-98">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-98">&#182;</a>
              </div>
              <p>Issue an error if the emitter isn’t a member of this group.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( emitterIndex === -<span class="hljs-number">1</span> ) {
        <span class="hljs-built_in">console</span>.error( <span class="hljs-string">'Emitter does not exist in this group. Will not remove.'</span> );
        <span class="hljs-keyword">return</span>;
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-99">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-99">&#182;</a>
              </div>
              <p>Kill all particles by marking them as dead
and their age as 0.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">var</span> start = emitter.attributeOffset,
        end = start + emitter.particleCount,
        params = <span class="hljs-keyword">this</span>.attributes.params.typedArray;</pre></div></div>
            
        </li>
        
        
        <li id="section-100">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-100">&#182;</a>
              </div>
              <p>Set alive and age to zero.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = start; i &lt; end; ++i ) {
        params.array[ i * <span class="hljs-number">4</span> ] = <span class="hljs-number">0.0</span>;
        params.array[ i * <span class="hljs-number">4</span> + <span class="hljs-number">1</span> ] = <span class="hljs-number">0.0</span>;
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-101">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-101">&#182;</a>
              </div>
              <p>Remove the emitter from this group’s “store”.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.emitters.splice( emitterIndex, <span class="hljs-number">1</span> );
    <span class="hljs-keyword">this</span>.emitterIDs.splice( emitterIndex, <span class="hljs-number">1</span> );</pre></div></div>
            
        </li>
        
        
        <li id="section-102">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-102">&#182;</a>
              </div>
              <p>Remove this emitter’s attribute values from all shader attributes.
The <code>.splice()</code> call here also marks each attribute’s buffer
as needing to update it’s entire contents.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> attr <span class="hljs-keyword">in</span> <span class="hljs-keyword">this</span>.attributes ) {
        <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.attributes.hasOwnProperty( attr ) ) {
            <span class="hljs-keyword">this</span>.attributes[ attr ].splice( start, end );
        }
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-103">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-103">&#182;</a>
              </div>
              <p>Ensure this group’s particle count is correct.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.particleCount -= emitter.particleCount;</pre></div></div>
            
        </li>
        
        
        <li id="section-104">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-104">&#182;</a>
              </div>
              <p>Call the emitter’s remove method.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    emitter._onRemove();</pre></div></div>
            
        </li>
        
        
        <li id="section-105">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-105">&#182;</a>
              </div>
              <p>Set a flag to indicate that the attribute buffers should
be updated in their entirety on the next frame.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>._attributesNeedRefresh = <span class="hljs-literal">true</span>;
};


<span class="hljs-comment">/**
 * Fetch a single emitter instance from the pool.
 * If there are no objects in the pool, a new emitter will be
 * created if specified.
 *
 * @return {Emitter|null}
 */</span>
SPE.Group.prototype.getFromPool = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> pool = <span class="hljs-keyword">this</span>._pool,
        createNew = <span class="hljs-keyword">this</span>._createNewWhenPoolEmpty;

    <span class="hljs-keyword">if</span> ( pool.length ) {
        <span class="hljs-keyword">return</span> pool.pop();
    }
    <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( createNew ) {
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> SPE.Emitter( <span class="hljs-keyword">this</span>._poolCreationSettings );
    }

    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
};


<span class="hljs-comment">/**
 * Release an emitter into the pool.
 *
 * @param  {ShaderParticleEmitter} emitter
 * @return {Group} This group instance.
 */</span>
SPE.Group.prototype.releaseIntoPool = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> emitter </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">if</span> ( emitter <span class="hljs-keyword">instanceof</span> SPE.Emitter === <span class="hljs-literal">false</span> ) {
        <span class="hljs-built_in">console</span>.error( <span class="hljs-string">'Argument is not instanceof SPE.Emitter:'</span>, emitter );
        <span class="hljs-keyword">return</span>;
    }

    emitter.reset();
    <span class="hljs-keyword">this</span>._pool.unshift( emitter );

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};


<span class="hljs-comment">/**
 * Get the pool array
 *
 * @return {Array}
 */</span>
SPE.Group.prototype.getPool = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>._pool;
};


<span class="hljs-comment">/**
 * Add a pool of emitters to this particle group
 *
 * @param {Number} numEmitters      The number of emitters to add to the pool.
 * @param {EmitterOptions|Array} emitterOptions  An object, or array of objects, describing the options to pass to each emitter.
 * @param {Boolean} createNew       Should a new emitter be created if the pool runs out?
 * @return {Group} This group instance.
 */</span>
SPE.Group.prototype.addPool = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> numEmitters, emitterOptions, createNew </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> emitter;</pre></div></div>
            
        </li>
        
        
        <li id="section-106">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-106">&#182;</a>
              </div>
              <p>Save relevant settings and flags.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>._poolCreationSettings = emitterOptions;
    <span class="hljs-keyword">this</span>._createNewWhenPoolEmpty = !!createNew;</pre></div></div>
            
        </li>
        
        
        <li id="section-107">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-107">&#182;</a>
              </div>
              <p>Create the emitters, add them to this group and the pool.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; numEmitters; ++i ) {
        <span class="hljs-keyword">if</span> ( <span class="hljs-built_in">Array</span>.isArray( emitterOptions ) ) {
            emitter = <span class="hljs-keyword">new</span> SPE.Emitter( emitterOptions[ i ] );
        }
        <span class="hljs-keyword">else</span> {
            emitter = <span class="hljs-keyword">new</span> SPE.Emitter( emitterOptions );
        }
        <span class="hljs-keyword">this</span>.addEmitter( emitter );
        <span class="hljs-keyword">this</span>.releaseIntoPool( emitter );
    }

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};



SPE.Group.prototype._triggerSingleEmitter = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> pos </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> emitter = <span class="hljs-keyword">this</span>.getFromPool(),
        self = <span class="hljs-keyword">this</span>;

    <span class="hljs-keyword">if</span> ( emitter === <span class="hljs-literal">null</span> ) {
        <span class="hljs-built_in">console</span>.log( <span class="hljs-string">'SPE.Group pool ran out.'</span> );
        <span class="hljs-keyword">return</span>;
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-108">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-108">&#182;</a>
              </div>
              <p>TODO:</p>
<ul>
<li>Make sure buffers are update with thus new position.</li>
</ul>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> ( pos <span class="hljs-keyword">instanceof</span> THREE.Vector3 ) {
        emitter.position.value.copy( pos );</pre></div></div>
            
        </li>
        
        
        <li id="section-109">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-109">&#182;</a>
              </div>
              <p>Trigger the setter for this property to force an
update to the emitter’s position attribute.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        emitter.position.value = emitter.position.value;
    }

    emitter.enable();

    setTimeout( <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
        emitter.disable();
        self.releaseIntoPool( emitter );
    }, ( emitter.maxAge.value + emitter.maxAge.spread ) * <span class="hljs-number">1000</span> );

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};


<span class="hljs-comment">/**
 * Set a given number of emitters as alive, with an optional position
 * vector3 to move them to.
 *
 * @param  {Number} numEmitters The number of emitters to activate
 * @param  {Object} [position=undefined] A THREE.Vector3 instance describing the position to activate the emitter(s) at.
 * @return {Group} This group instance.
 */</span>
SPE.Group.prototype.triggerPoolEmitter = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> numEmitters, position </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">typeof</span> numEmitters === <span class="hljs-string">'number'</span> &amp;&amp; numEmitters &gt; <span class="hljs-number">1</span> ) {
        <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>; i &lt; numEmitters; ++i ) {
            <span class="hljs-keyword">this</span>._triggerSingleEmitter( position );
        }
    }
    <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">this</span>._triggerSingleEmitter( position );
    }

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};



SPE.Group.prototype._updateUniforms = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> dt </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.uniforms.runTime.value += dt;
    <span class="hljs-keyword">this</span>.uniforms.deltaTime.value = dt;
};

SPE.Group.prototype._resetBufferRanges = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> keys = <span class="hljs-keyword">this</span>.attributeKeys,
        i = <span class="hljs-keyword">this</span>.attributeCount - <span class="hljs-number">1</span>,
        attrs = <span class="hljs-keyword">this</span>.attributes;

    <span class="hljs-keyword">for</span> ( i; i &gt;= <span class="hljs-number">0</span>; --i ) {
        attrs[ keys[ i ] ].resetUpdateRange();
    }
};


SPE.Group.prototype._updateBuffers = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> emitter </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> keys = <span class="hljs-keyword">this</span>.attributeKeys,
        i = <span class="hljs-keyword">this</span>.attributeCount - <span class="hljs-number">1</span>,
        attrs = <span class="hljs-keyword">this</span>.attributes,
        emitterRanges = emitter.bufferUpdateRanges,
        key,
        emitterAttr,
        attr;

    <span class="hljs-keyword">for</span> ( i; i &gt;= <span class="hljs-number">0</span>; --i ) {
        key = keys[ i ];
        emitterAttr = emitterRanges[ key ];
        attr = attrs[ key ];
        attr.setUpdateRange( emitterAttr.min, emitterAttr.max );
        attr.flagUpdate();
    }
};


<span class="hljs-comment">/**
 * Simulate all the emitter's belonging to this group, updating
 * attribute values along the way.
 * @param  {Number} [dt=Group's `fixedTimeStep` value] The number of seconds to simulate the group's emitters for (deltaTime)
 */</span>
SPE.Group.prototype.tick = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> dt </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> emitters = <span class="hljs-keyword">this</span>.emitters,
        numEmitters = emitters.length,
        deltaTime = dt || <span class="hljs-keyword">this</span>.fixedTimeStep,
        keys = <span class="hljs-keyword">this</span>.attributeKeys,
        i,
        attrs = <span class="hljs-keyword">this</span>.attributes;</pre></div></div>
            
        </li>
        
        
        <li id="section-110">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-110">&#182;</a>
              </div>
              <p>Update uniform values.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>._updateUniforms( deltaTime );</pre></div></div>
            
        </li>
        
        
        <li id="section-111">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-111">&#182;</a>
              </div>
              <p>Reset buffer update ranges on the shader attributes.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>._resetBufferRanges();</pre></div></div>
            
        </li>
        
        
        <li id="section-112">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-112">&#182;</a>
              </div>
              <p>If nothing needs updating, then stop here.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> (
        numEmitters === <span class="hljs-number">0</span> &amp;&amp;
        <span class="hljs-keyword">this</span>._attributesNeedRefresh === <span class="hljs-literal">false</span> &amp;&amp;
        <span class="hljs-keyword">this</span>._attributesNeedDynamicReset === <span class="hljs-literal">false</span>
    ) {
        <span class="hljs-keyword">return</span>;
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-113">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-113">&#182;</a>
              </div>
              <p>Loop through each emitter in this group and
simulate it, then update the shader attribute
buffers.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = <span class="hljs-number">0</span>, emitter; i &lt; numEmitters; ++i ) {
        emitter = emitters[ i ];
        emitter.tick( deltaTime );
        <span class="hljs-keyword">this</span>._updateBuffers( emitter );
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-114">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-114">&#182;</a>
              </div>
              <p>If the shader attributes have been refreshed,
then the dynamic properties of each buffer
attribute will need to be reset back to
what they should be.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>._attributesNeedDynamicReset === <span class="hljs-literal">true</span> ) {
        i = <span class="hljs-keyword">this</span>.attributeCount - <span class="hljs-number">1</span>;

        <span class="hljs-keyword">for</span> ( i; i &gt;= <span class="hljs-number">0</span>; --i ) {
            attrs[ keys[ i ] ].resetDynamic();
        }

        <span class="hljs-keyword">this</span>._attributesNeedDynamicReset = <span class="hljs-literal">false</span>;
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-115">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-115">&#182;</a>
              </div>
              <p>If this group’s shader attributes need a full refresh
then mark each attribute’s buffer attribute as
needing so.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>._attributesNeedRefresh === <span class="hljs-literal">true</span> ) {
        i = <span class="hljs-keyword">this</span>.attributeCount - <span class="hljs-number">1</span>;

        <span class="hljs-keyword">for</span> ( i; i &gt;= <span class="hljs-number">0</span>; --i ) {
            attrs[ keys[ i ] ].forceUpdateAll();
        }

        <span class="hljs-keyword">this</span>._attributesNeedRefresh = <span class="hljs-literal">false</span>;
        <span class="hljs-keyword">this</span>._attributesNeedDynamicReset = <span class="hljs-literal">true</span>;
    }
};


<span class="hljs-comment">/**
 * Dipose the geometry and material for the group.
 *
 * @return {Group} Group instance.
 */</span>
SPE.Group.prototype.dispose = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;
    <span class="hljs-keyword">this</span>.geometry.dispose();
    <span class="hljs-keyword">this</span>.material.dispose();
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};

<span class="hljs-comment">/**
 * An SPE.Emitter instance.
 * @typedef {Object} Emitter
 * @see SPE.Emitter
 */</span>

<span class="hljs-comment">/**
 * A map of options to configure an SPE.Emitter instance.
 *
 * @typedef {Object} EmitterOptions
 *
 * @property {distribution} [type=BOX] The default distribution this emitter should use to control
 *                         its particle's spawn position and force behaviour.
 *                         Must be an SPE.distributions.* value.
 *
 *
 * @property {Number} [particleCount=100] The total number of particles this emitter will hold. <span class="hljs-doctag">NOTE:</span> this is not the number
 *                                  of particles emitted in a second, or anything like that. The number of particles
 *                                  emitted per-second is calculated by particleCount / maxAge (approximately!)
 *
 * @property {Number|null} [duration=null] The duration in seconds that this emitter should live for. If not specified, the emitter
 *                                         will emit particles indefinitely.
 *                                         <span class="hljs-doctag">NOTE:</span> When an emitter is older than a specified duration, the emitter is NOT removed from
 *                                         it's group, but rather is just marked as dead, allowing it to be reanimated at a later time
 *                                         using `SPE.Emitter.prototype.enable()`.
 *
 * @property {Boolean} [isStatic=false] Whether this emitter should be not be simulated (true).
 * @property {Boolean} [activeMultiplier=1] A value between 0 and 1 describing what percentage of this emitter's particlesPerSecond should be
 *                                          emitted, where 0 is 0%, and 1 is 100%.
 *                                          For example, having an emitter with 100 particles, a maxAge of 2, yields a particlesPerSecond
 *                                          value of 50. Setting `activeMultiplier` to 0.5, then, will only emit 25 particles per second (0.5 = 50%).
 *                                          Values greater than 1 will emulate a burst of particles, causing the emitter to run out of particles
 *                                          before it's next activation cycle.
 *
 * @property {Boolean} [direction=1] The direction of the emitter. If value is `1`, emitter will start at beginning of particle's lifecycle.
 *                                   If value is `-1`, emitter will start at end of particle's lifecycle and work it's way backwards.
 *
 * @property {Object} [maxAge={}] An object describing the particle's maximum age in seconds.
 * @property {Number} [maxAge.value=2] A number between 0 and 1 describing the amount of maxAge to apply to all particles.
 * @property {Number} [maxAge.spread=0] A number describing the maxAge variance on a per-particle basis.
 *
 *
 * @property {Object} [position={}] An object describing this emitter's position.
 * @property {Object} [position.value=new THREE.Vector3()] A THREE.Vector3 instance describing this emitter's base position.
 * @property {Object} [position.spread=new THREE.Vector3()] A THREE.Vector3 instance describing this emitter's position variance on a per-particle basis.
 *                                                          Note that when using a SPHERE or DISC distribution, only the x-component
 *                                                          of this vector is used.
 * @property {Object} [position.spreadClamp=new THREE.Vector3()] A THREE.Vector3 instance describing the numeric multiples the particle's should
 *                                                               be spread out over.
 *                                                               Note that when using a SPHERE or DISC distribution, only the x-component
 *                                                               of this vector is used.
 * @property {Number} [position.radius=10] This emitter's base radius.
 * @property {Object} [position.radiusScale=new THREE.Vector3()] A THREE.Vector3 instance describing the radius's scale in all three axes. Allows a SPHERE or DISC to be squashed or stretched.
 * @property {distribution} [position.distribution=value of the `type` option.] A specific distribution to use when radiusing particles. Overrides the `type` option.
 * @property {Boolean} [position.randomise=false] When a particle is re-spawned, whether it's position should be re-randomised or not. Can incur a performance hit.
 *
 *
 * @property {Object} [velocity={}] An object describing this particle velocity.
 * @property {Object} [velocity.value=new THREE.Vector3()] A THREE.Vector3 instance describing this emitter's base velocity.
 * @property {Object} [velocity.spread=new THREE.Vector3()] A THREE.Vector3 instance describing this emitter's velocity variance on a per-particle basis.
 *                                                          Note that when using a SPHERE or DISC distribution, only the x-component
 *                                                          of this vector is used.
 * @property {distribution} [velocity.distribution=value of the `type` option.] A specific distribution to use when calculating a particle's velocity. Overrides the `type` option.
 * @property {Boolean} [velocity.randomise=false] When a particle is re-spawned, whether it's velocity should be re-randomised or not. Can incur a performance hit.
 *
 *
 * @property {Object} [acceleration={}] An object describing this particle's acceleration.
 * @property {Object} [acceleration.value=new THREE.Vector3()] A THREE.Vector3 instance describing this emitter's base acceleration.
 * @property {Object} [acceleration.spread=new THREE.Vector3()] A THREE.Vector3 instance describing this emitter's acceleration variance on a per-particle basis.
 *                           Note that when using a SPHERE or DISC distribution, only the x-component
 *                           of this vector is used.
 * @property {distribution} [acceleration.distribution=value of the `type` option.] A specific distribution to use when calculating a particle's acceleration. Overrides the `type` option.
 * @property {Boolean} [acceleration.randomise=false] When a particle is re-spawned, whether it's acceleration should be re-randomised or not. Can incur a performance hit.
 *
 *
 * @property {Object} [drag={}] An object describing this particle drag. Drag is applied to both velocity and acceleration values.
 * @property {Number} [drag.value=0] A number between 0 and 1 describing the amount of drag to apply to all particles.
 * @property {Number} [drag.spread=0] A number describing the drag variance on a per-particle basis.
 * @property {Boolean} [drag.randomise=false] When a particle is re-spawned, whether it's drag should be re-randomised or not. Can incur a performance hit.
 *
 *
 * @property {Object} [wiggle={}] This is quite a fun one! The values of this object will determine whether a particle will wiggle, or jiggle, or wave,
 *                                or shimmy, or waggle, or... Well you get the idea. The wiggle is calculated over-time, meaning that a particle will
 *                                start off with no wiggle, and end up wiggling about with the distance of the `value` specified by the time it dies.
 *                                It's quite handy to simulate fire embers, or similar effects where the particle's position should slightly change over
 *                                time, and such change isn't easily controlled by rotation, velocity, or acceleration. The wiggle is a combination of sin and cos calculations, so is circular in nature.
 * @property {Number} [wiggle.value=0] A number describing the amount of wiggle to apply to all particles. It's measured in distance.
 * @property {Number} [wiggle.spread=0] A number describing the wiggle variance on a per-particle basis.
 *
 *
 * @property {Object} [rotation={}] An object describing this emitter's rotation. It can either be static, or set to rotate from 0radians to the value of `rotation.value`
 *                                  over a particle's lifetime. Rotation values affect both a particle's position and the forces applied to it.
 * @property {Object} [rotation.axis=new THREE.Vector3(0, 1, 0)] A THREE.Vector3 instance describing this emitter's axis of rotation.
 * @property {Object} [rotation.axisSpread=new THREE.Vector3()] A THREE.Vector3 instance describing the amount of variance to apply to the axis of rotation on
 *                                                              a per-particle basis.
 * @property {Number} [rotation.angle=0] The angle of rotation, given in radians. If `rotation.static` is true, the emitter will start off rotated at this angle, and stay as such.
 *                                       Otherwise, the particles will rotate from 0radians to this value over their lifetimes.
 * @property {Number} [rotation.angleSpread=0] The amount of variance in each particle's rotation angle.
 * @property {Boolean} [rotation.static=false] Whether the rotation should be static or not.
 * @property {Object} [rotation.center=The value of `position.value`] A THREE.Vector3 instance describing the center point of rotation.
 * @property {Boolean} [rotation.randomise=false] When a particle is re-spawned, whether it's rotation should be re-randomised or not. Can incur a performance hit.
 *
 *
 * @property {Object} [color={}] An object describing a particle's color. This property is a "value-over-lifetime" property, meaning an array of values and spreads can be
 *                               given to describe specific value changes over a particle's lifetime.
 *                               Depending on the value of SPE.valueOverLifetimeLength, if arrays of THREE.Color instances are given, then the array will be interpolated to
 *                               have a length matching the value of SPE.valueOverLifetimeLength.
 * @property {Object} [color.value=new THREE.Color()] Either a single THREE.Color instance, or an array of THREE.Color instances to describe the color of a particle over it's lifetime.
 * @property {Object} [color.spread=new THREE.Vector3()] Either a single THREE.Vector3 instance, or an array of THREE.Vector3 instances to describe the color variance of a particle over it's lifetime.
 * @property {Boolean} [color.randomise=false] When a particle is re-spawned, whether it's color should be re-randomised or not. Can incur a performance hit.
 *
 *
 * @property {Object} [opacity={}] An object describing a particle's opacity. This property is a "value-over-lifetime" property, meaning an array of values and spreads can be
 *                               given to describe specific value changes over a particle's lifetime.
 *                               Depending on the value of SPE.valueOverLifetimeLength, if arrays of numbers are given, then the array will be interpolated to
 *                               have a length matching the value of SPE.valueOverLifetimeLength.
 * @property {Number} [opacity.value=1] Either a single number, or an array of numbers to describe the opacity of a particle over it's lifetime.
 * @property {Number} [opacity.spread=0] Either a single number, or an array of numbers to describe the opacity variance of a particle over it's lifetime.
 * @property {Boolean} [opacity.randomise=false] When a particle is re-spawned, whether it's opacity should be re-randomised or not. Can incur a performance hit.
 *
 *
 * @property {Object} [size={}] An object describing a particle's size. This property is a "value-over-lifetime" property, meaning an array of values and spreads can be
 *                               given to describe specific value changes over a particle's lifetime.
 *                               Depending on the value of SPE.valueOverLifetimeLength, if arrays of numbers are given, then the array will be interpolated to
 *                               have a length matching the value of SPE.valueOverLifetimeLength.
 * @property {Number} [size.value=1] Either a single number, or an array of numbers to describe the size of a particle over it's lifetime.
 * @property {Number} [size.spread=0] Either a single number, or an array of numbers to describe the size variance of a particle over it's lifetime.
 * @property {Boolean} [size.randomise=false] When a particle is re-spawned, whether it's size should be re-randomised or not. Can incur a performance hit.
 *
 *
 * @property {Object} [angle={}] An object describing a particle's angle. The angle is a 2d-rotation, measured in radians, applied to the particle's texture.
 *                               <span class="hljs-doctag">NOTE:</span> if a particle's texture is a sprite-sheet, this value IS IGNORED.
 *                               This property is a "value-over-lifetime" property, meaning an array of values and spreads can be
 *                               given to describe specific value changes over a particle's lifetime.
 *                               Depending on the value of SPE.valueOverLifetimeLength, if arrays of numbers are given, then the array will be interpolated to
 *                               have a length matching the value of SPE.valueOverLifetimeLength.
 * @property {Number} [angle.value=0] Either a single number, or an array of numbers to describe the angle of a particle over it's lifetime.
 * @property {Number} [angle.spread=0] Either a single number, or an array of numbers to describe the angle variance of a particle over it's lifetime.
 * @property {Boolean} [angle.randomise=false] When a particle is re-spawned, whether it's angle should be re-randomised or not. Can incur a performance hit.
 *
 */</span>

<span class="hljs-comment">/**
 * The SPE.Emitter class.
 *
 * @constructor
 *
 * @param {EmitterOptions} options A map of options to configure the emitter.
 */</span>
SPE.Emitter = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> options </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> utils = SPE.utils,
        types = utils.types,
        lifetimeLength = SPE.valueOverLifetimeLength;</pre></div></div>
            
        </li>
        
        
        <li id="section-116">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-116">&#182;</a>
              </div>
              <p>Ensure we have a map of options to play with,
and that each option is in the correct format.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    options = utils.ensureTypedArg( options, types.OBJECT, {} );
    options.position = utils.ensureTypedArg( options.position, types.OBJECT, {} );
    options.velocity = utils.ensureTypedArg( options.velocity, types.OBJECT, {} );
    options.acceleration = utils.ensureTypedArg( options.acceleration, types.OBJECT, {} );
    options.radius = utils.ensureTypedArg( options.radius, types.OBJECT, {} );
    options.drag = utils.ensureTypedArg( options.drag, types.OBJECT, {} );
    options.rotation = utils.ensureTypedArg( options.rotation, types.OBJECT, {} );
    options.color = utils.ensureTypedArg( options.color, types.OBJECT, {} );
    options.opacity = utils.ensureTypedArg( options.opacity, types.OBJECT, {} );
    options.size = utils.ensureTypedArg( options.size, types.OBJECT, {} );
    options.angle = utils.ensureTypedArg( options.angle, types.OBJECT, {} );
    options.wiggle = utils.ensureTypedArg( options.wiggle, types.OBJECT, {} );
    options.maxAge = utils.ensureTypedArg( options.maxAge, types.OBJECT, {} );

    <span class="hljs-keyword">if</span> ( options.onParticleSpawn ) {
        <span class="hljs-built_in">console</span>.warn( <span class="hljs-string">'onParticleSpawn has been removed. Please set properties directly to alter values at runtime.'</span> );
    }

    <span class="hljs-keyword">this</span>.uuid = THREE.Math.generateUUID();

    <span class="hljs-keyword">this</span>.type = utils.ensureTypedArg( options.type, types.NUMBER, SPE.distributions.BOX );</pre></div></div>
            
        </li>
        
        
        <li id="section-117">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-117">&#182;</a>
              </div>
              <p>Start assigning properties…kicking it off with props that DON’T support values over
lifetimes.</p>
<p>Btw, values over lifetimes are just the new way of referring to <em>Start, </em>Middle, and *End.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.position = {
        _value: utils.ensureInstanceOf( options.position.value, THREE.Vector3, <span class="hljs-keyword">new</span> THREE.Vector3() ),
        _spread: utils.ensureInstanceOf( options.position.spread, THREE.Vector3, <span class="hljs-keyword">new</span> THREE.Vector3() ),
        _spreadClamp: utils.ensureInstanceOf( options.position.spreadClamp, THREE.Vector3, <span class="hljs-keyword">new</span> THREE.Vector3() ),
        _distribution: utils.ensureTypedArg( options.position.distribution, types.NUMBER, <span class="hljs-keyword">this</span>.type ),
        _randomise: utils.ensureTypedArg( options.position.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> ),
        _radius: utils.ensureTypedArg( options.position.radius, types.NUMBER, <span class="hljs-number">10</span> ),
        _radiusScale: utils.ensureInstanceOf( options.position.radiusScale, THREE.Vector3, <span class="hljs-keyword">new</span> THREE.Vector3( <span class="hljs-number">1</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span> ) ),
        _distributionClamp: utils.ensureTypedArg( options.position.distributionClamp, types.NUMBER, <span class="hljs-number">0</span> ),
    };

    <span class="hljs-keyword">this</span>.velocity = {
        _value: utils.ensureInstanceOf( options.velocity.value, THREE.Vector3, <span class="hljs-keyword">new</span> THREE.Vector3() ),
        _spread: utils.ensureInstanceOf( options.velocity.spread, THREE.Vector3, <span class="hljs-keyword">new</span> THREE.Vector3() ),
        _distribution: utils.ensureTypedArg( options.velocity.distribution, types.NUMBER, <span class="hljs-keyword">this</span>.type ),
        _randomise: utils.ensureTypedArg( options.position.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> )
    };

    <span class="hljs-keyword">this</span>.acceleration = {
        _value: utils.ensureInstanceOf( options.acceleration.value, THREE.Vector3, <span class="hljs-keyword">new</span> THREE.Vector3() ),
        _spread: utils.ensureInstanceOf( options.acceleration.spread, THREE.Vector3, <span class="hljs-keyword">new</span> THREE.Vector3() ),
        _distribution: utils.ensureTypedArg( options.acceleration.distribution, types.NUMBER, <span class="hljs-keyword">this</span>.type ),
        _randomise: utils.ensureTypedArg( options.position.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> )
    };

    <span class="hljs-keyword">this</span>.drag = {
        _value: utils.ensureTypedArg( options.drag.value, types.NUMBER, <span class="hljs-number">0</span> ),
        _spread: utils.ensureTypedArg( options.drag.spread, types.NUMBER, <span class="hljs-number">0</span> ),
        _randomise: utils.ensureTypedArg( options.position.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> )
    };

    <span class="hljs-keyword">this</span>.wiggle = {
        _value: utils.ensureTypedArg( options.wiggle.value, types.NUMBER, <span class="hljs-number">0</span> ),
        _spread: utils.ensureTypedArg( options.wiggle.spread, types.NUMBER, <span class="hljs-number">0</span> )
    };

    <span class="hljs-keyword">this</span>.rotation = {
        _axis: utils.ensureInstanceOf( options.rotation.axis, THREE.Vector3, <span class="hljs-keyword">new</span> THREE.Vector3( <span class="hljs-number">0.0</span>, <span class="hljs-number">1.0</span>, <span class="hljs-number">0.0</span> ) ),
        _axisSpread: utils.ensureInstanceOf( options.rotation.axisSpread, THREE.Vector3, <span class="hljs-keyword">new</span> THREE.Vector3() ),
        _angle: utils.ensureTypedArg( options.rotation.angle, types.NUMBER, <span class="hljs-number">0</span> ),
        _angleSpread: utils.ensureTypedArg( options.rotation.angleSpread, types.NUMBER, <span class="hljs-number">0</span> ),
        _static: utils.ensureTypedArg( options.rotation.static, types.BOOLEAN, <span class="hljs-literal">false</span> ),
        _center: utils.ensureInstanceOf( options.rotation.center, THREE.Vector3, <span class="hljs-keyword">this</span>.position._value.clone() ),
        _randomise: utils.ensureTypedArg( options.position.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> )
    };


    <span class="hljs-keyword">this</span>.maxAge = {
        _value: utils.ensureTypedArg( options.maxAge.value, types.NUMBER, <span class="hljs-number">2</span> ),
        _spread: utils.ensureTypedArg( options.maxAge.spread, types.NUMBER, <span class="hljs-number">0</span> )
    };</pre></div></div>
            
        </li>
        
        
        <li id="section-118">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-118">&#182;</a>
              </div>
              <p>The following properties can support either single values, or an array of values that change
the property over a particle’s lifetime (value over lifetime).</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.color = {
        _value: utils.ensureArrayInstanceOf( options.color.value, THREE.Color, <span class="hljs-keyword">new</span> THREE.Color() ),
        _spread: utils.ensureArrayInstanceOf( options.color.spread, THREE.Vector3, <span class="hljs-keyword">new</span> THREE.Vector3() ),
        _randomise: utils.ensureTypedArg( options.position.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> )
    };

    <span class="hljs-keyword">this</span>.opacity = {
        _value: utils.ensureArrayTypedArg( options.opacity.value, types.NUMBER, <span class="hljs-number">1</span> ),
        _spread: utils.ensureArrayTypedArg( options.opacity.spread, types.NUMBER, <span class="hljs-number">0</span> ),
        _randomise: utils.ensureTypedArg( options.position.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> )
    };

    <span class="hljs-keyword">this</span>.size = {
        _value: utils.ensureArrayTypedArg( options.size.value, types.NUMBER, <span class="hljs-number">1</span> ),
        _spread: utils.ensureArrayTypedArg( options.size.spread, types.NUMBER, <span class="hljs-number">0</span> ),
        _randomise: utils.ensureTypedArg( options.position.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> )
    };

    <span class="hljs-keyword">this</span>.angle = {
        _value: utils.ensureArrayTypedArg( options.angle.value, types.NUMBER, <span class="hljs-number">0</span> ),
        _spread: utils.ensureArrayTypedArg( options.angle.spread, types.NUMBER, <span class="hljs-number">0</span> ),
        _randomise: utils.ensureTypedArg( options.position.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> )
    };</pre></div></div>
            
        </li>
        
        
        <li id="section-119">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-119">&#182;</a>
              </div>
              <p>Assign renaining option values.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.particleCount = utils.ensureTypedArg( options.particleCount, types.NUMBER, <span class="hljs-number">100</span> );
    <span class="hljs-keyword">this</span>.duration = utils.ensureTypedArg( options.duration, types.NUMBER, <span class="hljs-literal">null</span> );
    <span class="hljs-keyword">this</span>.isStatic = utils.ensureTypedArg( options.isStatic, types.BOOLEAN, <span class="hljs-literal">false</span> );
    <span class="hljs-keyword">this</span>.activeMultiplier = utils.ensureTypedArg( options.activeMultiplier, types.NUMBER, <span class="hljs-number">1</span> );
    <span class="hljs-keyword">this</span>.direction = utils.ensureTypedArg( options.direction, types.NUMBER, <span class="hljs-number">1</span> );</pre></div></div>
            
        </li>
        
        
        <li id="section-120">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-120">&#182;</a>
              </div>
              <p>Whether this emitter is alive or not.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.alive = utils.ensureTypedArg( options.alive, types.BOOLEAN, <span class="hljs-literal">true</span> );</pre></div></div>
            
        </li>
        
        
        <li id="section-121">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-121">&#182;</a>
              </div>
              <p>The following properties are set internally and are not
user-controllable.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.particlesPerSecond = <span class="hljs-number">0</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-122">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-122">&#182;</a>
              </div>
              <p>The current particle index for which particles should
be marked as active on the next update cycle.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.activationIndex = <span class="hljs-number">0</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-123">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-123">&#182;</a>
              </div>
              <p>The offset in the typed arrays this emitter’s
particle’s values will start at</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.attributeOffset = <span class="hljs-number">0</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-124">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-124">&#182;</a>
              </div>
              <p>The end of the range in the attribute buffers</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.attributeEnd = <span class="hljs-number">0</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-125">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-125">&#182;</a>
              </div>
              <p>Holds the time the emitter has been alive for.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.age = <span class="hljs-number">0.0</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-126">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-126">&#182;</a>
              </div>
              <p>Holds the number of currently-alive particles</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.activeParticleCount = <span class="hljs-number">0.0</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-127">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-127">&#182;</a>
              </div>
              <p>Holds a reference to this emitter’s group once
it’s added to one.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.group = <span class="hljs-literal">null</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-128">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-128">&#182;</a>
              </div>
              <p>Holds a reference to this emitter’s group’s attributes object
for easier access.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.attributes = <span class="hljs-literal">null</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-129">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-129">&#182;</a>
              </div>
              <p>Holds a reference to the params attribute’s typed array
for quicker access.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.paramsArray = <span class="hljs-literal">null</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-130">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-130">&#182;</a>
              </div>
              <p>A set of flags to determine whether particular properties
should be re-randomised when a particle is reset.</p>
<p>If a <code>randomise</code> property is given, this is preferred.
Otherwise, it looks at whether a spread value has been
given.</p>
<p>It allows randomization to be turned off as desired. If
all randomization is turned off, then I’d expect a performance
boost as no attribute buffers (excluding the <code>params</code>)
would have to be re-passed to the GPU each frame (since nothing
except the <code>params</code> attribute would have changed).</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.resetFlags = {</pre></div></div>
            
        </li>
        
        
        <li id="section-131">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-131">&#182;</a>
              </div>
              <p>params: utils.ensureTypedArg( options.maxAge.randomise, types.BOOLEAN, !!options.maxAge.spread ) ||
    utils.ensureTypedArg( options.wiggle.randomise, types.BOOLEAN, !!options.wiggle.spread ),</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        position: utils.ensureTypedArg( options.position.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> ) ||
            utils.ensureTypedArg( options.radius.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> ),
        velocity: utils.ensureTypedArg( options.velocity.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> ),
        acceleration: utils.ensureTypedArg( options.acceleration.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> ) ||
            utils.ensureTypedArg( options.drag.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> ),
        rotation: utils.ensureTypedArg( options.rotation.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> ),
        rotationCenter: utils.ensureTypedArg( options.rotation.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> ),
        size: utils.ensureTypedArg( options.size.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> ),
        color: utils.ensureTypedArg( options.color.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> ),
        opacity: utils.ensureTypedArg( options.opacity.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> ),
        angle: utils.ensureTypedArg( options.angle.randomise, types.BOOLEAN, <span class="hljs-literal">false</span> )
    };

    <span class="hljs-keyword">this</span>.updateFlags = {};
    <span class="hljs-keyword">this</span>.updateCounts = {};</pre></div></div>
            
        </li>
        
        
        <li id="section-132">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-132">&#182;</a>
              </div>
              <p>A map to indicate which emitter parameters should update
which attribute.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.updateMap = {
        maxAge: <span class="hljs-string">'params'</span>,
        position: <span class="hljs-string">'position'</span>,
        velocity: <span class="hljs-string">'velocity'</span>,
        acceleration: <span class="hljs-string">'acceleration'</span>,
        drag: <span class="hljs-string">'acceleration'</span>,
        wiggle: <span class="hljs-string">'params'</span>,
        rotation: <span class="hljs-string">'rotation'</span>,
        size: <span class="hljs-string">'size'</span>,
        color: <span class="hljs-string">'color'</span>,
        opacity: <span class="hljs-string">'opacity'</span>,
        angle: <span class="hljs-string">'angle'</span>
    };

    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i <span class="hljs-keyword">in</span> <span class="hljs-keyword">this</span>.updateMap ) {
        <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.updateMap.hasOwnProperty( i ) ) {
            <span class="hljs-keyword">this</span>.updateCounts[ <span class="hljs-keyword">this</span>.updateMap[ i ] ] = <span class="hljs-number">0.0</span>;
            <span class="hljs-keyword">this</span>.updateFlags[ <span class="hljs-keyword">this</span>.updateMap[ i ] ] = <span class="hljs-literal">false</span>;
            <span class="hljs-keyword">this</span>._createGetterSetters( <span class="hljs-keyword">this</span>[ i ], i );
        }
    }

    <span class="hljs-keyword">this</span>.bufferUpdateRanges = {};
    <span class="hljs-keyword">this</span>.attributeKeys = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">this</span>.attributeCount = <span class="hljs-number">0</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-133">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-133">&#182;</a>
              </div>
              <p>Ensure that the value-over-lifetime property objects above
have value and spread properties that are of the same length.</p>
<p>Also, for now, make sure they have a length of 3 (min/max arguments here).</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    utils.ensureValueOverLifetimeCompliance( <span class="hljs-keyword">this</span>.color, lifetimeLength, lifetimeLength );
    utils.ensureValueOverLifetimeCompliance( <span class="hljs-keyword">this</span>.opacity, lifetimeLength, lifetimeLength );
    utils.ensureValueOverLifetimeCompliance( <span class="hljs-keyword">this</span>.size, lifetimeLength, lifetimeLength );
    utils.ensureValueOverLifetimeCompliance( <span class="hljs-keyword">this</span>.angle, lifetimeLength, lifetimeLength );
};

SPE.Emitter.constructor = SPE.Emitter;

SPE.Emitter.prototype._createGetterSetters = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> propObj, propName </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> self = <span class="hljs-keyword">this</span>;

    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i <span class="hljs-keyword">in</span> propObj ) {
        <span class="hljs-keyword">if</span> ( propObj.hasOwnProperty( i ) ) {

            <span class="hljs-keyword">var</span> name = i.replace( <span class="hljs-string">'_'</span>, <span class="hljs-string">''</span> );

            <span class="hljs-built_in">Object</span>.defineProperty( propObj, name, {
                get: ( <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> prop </span>) </span>{
                    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
                        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>[ prop ];
                    };
                }( i ) ),

                set: ( <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> prop </span>) </span>{
                    <span class="hljs-keyword">return</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> value </span>) </span>{
                        <span class="hljs-keyword">var</span> mapName = self.updateMap[ propName ],
                            prevValue = <span class="hljs-keyword">this</span>[ prop ],
                            length = SPE.valueOverLifetimeLength;

                        <span class="hljs-keyword">if</span> ( prop === <span class="hljs-string">'_rotationCenter'</span> ) {
                            self.updateFlags.rotationCenter = <span class="hljs-literal">true</span>;
                            self.updateCounts.rotationCenter = <span class="hljs-number">0.0</span>;
                        }
                        <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( prop === <span class="hljs-string">'_randomise'</span> ) {
                            self.resetFlags[ mapName ] = value;
                        }
                        <span class="hljs-keyword">else</span> {
                            self.updateFlags[ mapName ] = <span class="hljs-literal">true</span>;
                            self.updateCounts[ mapName ] = <span class="hljs-number">0.0</span>;
                        }

                        self.group._updateDefines();

                        <span class="hljs-keyword">this</span>[ prop ] = value;</pre></div></div>
            
        </li>
        
        
        <li id="section-134">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-134">&#182;</a>
              </div>
              <p>If the previous value was an array, then make
sure the provided value is interpolated correctly.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>                        <span class="hljs-keyword">if</span> ( <span class="hljs-built_in">Array</span>.isArray( prevValue ) ) {
                            SPE.utils.ensureValueOverLifetimeCompliance( self[ propName ], length, length );
                        }
                    };
                }( i ) )
            } );
        }
    }
};

SPE.Emitter.prototype._setBufferUpdateRanges = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> keys </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.attributeKeys = keys;
    <span class="hljs-keyword">this</span>.attributeCount = keys.length;

    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = <span class="hljs-keyword">this</span>.attributeCount - <span class="hljs-number">1</span>; i &gt;= <span class="hljs-number">0</span>; --i ) {
        <span class="hljs-keyword">this</span>.bufferUpdateRanges[ keys[ i ] ] = {
            min: <span class="hljs-built_in">Number</span>.POSITIVE_INFINITY,
            max: <span class="hljs-built_in">Number</span>.NEGATIVE_INFINITY
        };
    }
};

SPE.Emitter.prototype._calculatePPSValue = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> groupMaxAge </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> particleCount = <span class="hljs-keyword">this</span>.particleCount;</pre></div></div>
            
        </li>
        
        
        <li id="section-135">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-135">&#182;</a>
              </div>
              <p>Calculate the <code>particlesPerSecond</code> value for this emitter. It’s used
when determining which particles should die and which should live to
see another day. Or be born, for that matter. The “God” property.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.duration ) {
        <span class="hljs-keyword">this</span>.particlesPerSecond = particleCount / ( groupMaxAge &lt; <span class="hljs-keyword">this</span>.duration ? groupMaxAge : <span class="hljs-keyword">this</span>.duration );
    }
    <span class="hljs-keyword">else</span> {
        <span class="hljs-keyword">this</span>.particlesPerSecond = particleCount / groupMaxAge;
    }
};

SPE.Emitter.prototype._setAttributeOffset = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> startIndex </span>) </span>{
    <span class="hljs-keyword">this</span>.attributeOffset = startIndex;
    <span class="hljs-keyword">this</span>.activationIndex = startIndex;
    <span class="hljs-keyword">this</span>.activationEnd = startIndex + <span class="hljs-keyword">this</span>.particleCount;
};


SPE.Emitter.prototype._assignValue = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> prop, index </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">switch</span> ( prop ) {
        <span class="hljs-keyword">case</span> <span class="hljs-string">'position'</span>:
            <span class="hljs-keyword">this</span>._assignPositionValue( index );
            <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> <span class="hljs-string">'velocity'</span>:
        <span class="hljs-keyword">case</span> <span class="hljs-string">'acceleration'</span>:
            <span class="hljs-keyword">this</span>._assignForceValue( index, prop );
            <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> <span class="hljs-string">'size'</span>:
        <span class="hljs-keyword">case</span> <span class="hljs-string">'opacity'</span>:
            <span class="hljs-keyword">this</span>._assignAbsLifetimeValue( index, prop );
            <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> <span class="hljs-string">'angle'</span>:
            <span class="hljs-keyword">this</span>._assignAngleValue( index );
            <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> <span class="hljs-string">'params'</span>:
            <span class="hljs-keyword">this</span>._assignParamsValue( index );
            <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> <span class="hljs-string">'rotation'</span>:
            <span class="hljs-keyword">this</span>._assignRotationValue( index );
            <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> <span class="hljs-string">'color'</span>:
            <span class="hljs-keyword">this</span>._assignColorValue( index );
            <span class="hljs-keyword">break</span>;
    }
};

SPE.Emitter.prototype._assignPositionValue = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> distributions = SPE.distributions,
        utils = SPE.utils,
        prop = <span class="hljs-keyword">this</span>.position,
        attr = <span class="hljs-keyword">this</span>.attributes.position,
        value = prop._value,
        spread = prop._spread,
        distribution = prop._distribution;

    <span class="hljs-keyword">switch</span> ( distribution ) {
        <span class="hljs-keyword">case</span> distributions.BOX:
            utils.randomVector3( attr, index, value, spread, prop._spreadClamp );
            <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> distributions.SPHERE:
            utils.randomVector3OnSphere( attr, index, value, prop._radius, prop._spread.x, prop._radiusScale, prop._spreadClamp.x, prop._distributionClamp || <span class="hljs-keyword">this</span>.particleCount );
            <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> distributions.DISC:
            utils.randomVector3OnDisc( attr, index, value, prop._radius, prop._spread.x, prop._radiusScale, prop._spreadClamp.x );
            <span class="hljs-keyword">break</span>;
    }
};

SPE.Emitter.prototype._assignForceValue = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, attrName </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> distributions = SPE.distributions,
        utils = SPE.utils,
        prop = <span class="hljs-keyword">this</span>[ attrName ],
        value = prop._value,
        spread = prop._spread,
        distribution = prop._distribution,
        pos,
        positionX,
        positionY,
        positionZ,
        i;

    <span class="hljs-keyword">switch</span> ( distribution ) {
        <span class="hljs-keyword">case</span> distributions.BOX:
            utils.randomVector3( <span class="hljs-keyword">this</span>.attributes[ attrName ], index, value, spread );
            <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> distributions.SPHERE:
            pos = <span class="hljs-keyword">this</span>.attributes.position.typedArray.array;
            i = index * <span class="hljs-number">3</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-136">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-136">&#182;</a>
              </div>
              <p>Ensure position values aren’t zero, otherwise no force will be
applied.
positionX = utils.zeroToEpsilon( pos[ i ], true );
positionY = utils.zeroToEpsilon( pos[ i + 1 ], true );
positionZ = utils.zeroToEpsilon( pos[ i + 2 ], true );</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>            positionX = pos[ i ];
            positionY = pos[ i + <span class="hljs-number">1</span> ];
            positionZ = pos[ i + <span class="hljs-number">2</span> ];

            utils.randomDirectionVector3OnSphere(
                <span class="hljs-keyword">this</span>.attributes[ attrName ], index,
                positionX, positionY, positionZ,
                <span class="hljs-keyword">this</span>.position._value,
                prop._value.x,
                prop._spread.x
            );
            <span class="hljs-keyword">break</span>;

        <span class="hljs-keyword">case</span> distributions.DISC:
            pos = <span class="hljs-keyword">this</span>.attributes.position.typedArray.array;
            i = index * <span class="hljs-number">3</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-137">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-137">&#182;</a>
              </div>
              <p>Ensure position values aren’t zero, otherwise no force will be
applied.
positionX = utils.zeroToEpsilon( pos[ i ], true );
positionY = utils.zeroToEpsilon( pos[ i + 1 ], true );
positionZ = utils.zeroToEpsilon( pos[ i + 2 ], true );</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>            positionX = pos[ i ];
            positionY = pos[ i + <span class="hljs-number">1</span> ];
            positionZ = pos[ i + <span class="hljs-number">2</span> ];

            utils.randomDirectionVector3OnDisc(
                <span class="hljs-keyword">this</span>.attributes[ attrName ], index,
                positionX, positionY, positionZ,
                <span class="hljs-keyword">this</span>.position._value,
                prop._value.x,
                prop._spread.x
            );
            <span class="hljs-keyword">break</span>;
    }

    <span class="hljs-keyword">if</span> ( attrName === <span class="hljs-string">'acceleration'</span> ) {
        <span class="hljs-keyword">var</span> drag = utils.clamp( utils.randomFloat( <span class="hljs-keyword">this</span>.drag._value, <span class="hljs-keyword">this</span>.drag._spread ), <span class="hljs-number">0</span>, <span class="hljs-number">1</span> );
        <span class="hljs-keyword">this</span>.attributes.acceleration.typedArray.array[ index * <span class="hljs-number">4</span> + <span class="hljs-number">3</span> ] = drag;
    }
};

SPE.Emitter.prototype._assignAbsLifetimeValue = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index, propName </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> array = <span class="hljs-keyword">this</span>.attributes[ propName ].typedArray,
        prop = <span class="hljs-keyword">this</span>[ propName ],
        utils = SPE.utils,
        value;

    <span class="hljs-keyword">if</span> ( utils.arrayValuesAreEqual( prop._value ) &amp;&amp; utils.arrayValuesAreEqual( prop._spread ) ) {
        value = <span class="hljs-built_in">Math</span>.abs( utils.randomFloat( prop._value[ <span class="hljs-number">0</span> ], prop._spread[ <span class="hljs-number">0</span> ] ) );
        array.setVec4Components( index, value, value, value, value );
    }
    <span class="hljs-keyword">else</span> {
        array.setVec4Components( index,
            <span class="hljs-built_in">Math</span>.abs( utils.randomFloat( prop._value[ <span class="hljs-number">0</span> ], prop._spread[ <span class="hljs-number">0</span> ] ) ),
            <span class="hljs-built_in">Math</span>.abs( utils.randomFloat( prop._value[ <span class="hljs-number">1</span> ], prop._spread[ <span class="hljs-number">1</span> ] ) ),
            <span class="hljs-built_in">Math</span>.abs( utils.randomFloat( prop._value[ <span class="hljs-number">2</span> ], prop._spread[ <span class="hljs-number">2</span> ] ) ),
            <span class="hljs-built_in">Math</span>.abs( utils.randomFloat( prop._value[ <span class="hljs-number">3</span> ], prop._spread[ <span class="hljs-number">3</span> ] ) )
        );
    }
};

SPE.Emitter.prototype._assignAngleValue = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> array = <span class="hljs-keyword">this</span>.attributes.angle.typedArray,
        prop = <span class="hljs-keyword">this</span>.angle,
        utils = SPE.utils,
        value;

    <span class="hljs-keyword">if</span> ( utils.arrayValuesAreEqual( prop._value ) &amp;&amp; utils.arrayValuesAreEqual( prop._spread ) ) {
        value = utils.randomFloat( prop._value[ <span class="hljs-number">0</span> ], prop._spread[ <span class="hljs-number">0</span> ] );
        array.setVec4Components( index, value, value, value, value );
    }
    <span class="hljs-keyword">else</span> {
        array.setVec4Components( index,
            utils.randomFloat( prop._value[ <span class="hljs-number">0</span> ], prop._spread[ <span class="hljs-number">0</span> ] ),
            utils.randomFloat( prop._value[ <span class="hljs-number">1</span> ], prop._spread[ <span class="hljs-number">1</span> ] ),
            utils.randomFloat( prop._value[ <span class="hljs-number">2</span> ], prop._spread[ <span class="hljs-number">2</span> ] ),
            utils.randomFloat( prop._value[ <span class="hljs-number">3</span> ], prop._spread[ <span class="hljs-number">3</span> ] )
        );
    }
};

SPE.Emitter.prototype._assignParamsValue = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.attributes.params.typedArray.setVec4Components( index,
        <span class="hljs-keyword">this</span>.isStatic ? <span class="hljs-number">1</span> : <span class="hljs-number">0</span>,
        <span class="hljs-number">0.0</span>,
        <span class="hljs-built_in">Math</span>.abs( SPE.utils.randomFloat( <span class="hljs-keyword">this</span>.maxAge._value, <span class="hljs-keyword">this</span>.maxAge._spread ) ),
        SPE.utils.randomFloat( <span class="hljs-keyword">this</span>.wiggle._value, <span class="hljs-keyword">this</span>.wiggle._spread )
    );
};

SPE.Emitter.prototype._assignRotationValue = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.attributes.rotation.typedArray.setVec3Components( index,
        SPE.utils.getPackedRotationAxis( <span class="hljs-keyword">this</span>.rotation._axis, <span class="hljs-keyword">this</span>.rotation._axisSpread ),
        SPE.utils.randomFloat( <span class="hljs-keyword">this</span>.rotation._angle, <span class="hljs-keyword">this</span>.rotation._angleSpread ),
        <span class="hljs-keyword">this</span>.rotation._static ? <span class="hljs-number">0</span> : <span class="hljs-number">1</span>
    );

    <span class="hljs-keyword">this</span>.attributes.rotationCenter.typedArray.setVec3( index, <span class="hljs-keyword">this</span>.rotation._center );
};

SPE.Emitter.prototype._assignColorValue = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;
    SPE.utils.randomColorAsHex( <span class="hljs-keyword">this</span>.attributes.color, index, <span class="hljs-keyword">this</span>.color._value, <span class="hljs-keyword">this</span>.color._spread );
};

SPE.Emitter.prototype._resetParticle = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> index </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> resetFlags = <span class="hljs-keyword">this</span>.resetFlags,
        updateFlags = <span class="hljs-keyword">this</span>.updateFlags,
        updateCounts = <span class="hljs-keyword">this</span>.updateCounts,
        keys = <span class="hljs-keyword">this</span>.attributeKeys,
        key,
        updateFlag;

    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = <span class="hljs-keyword">this</span>.attributeCount - <span class="hljs-number">1</span>; i &gt;= <span class="hljs-number">0</span>; --i ) {
        key = keys[ i ];
        updateFlag = updateFlags[ key ];

        <span class="hljs-keyword">if</span> ( resetFlags[ key ] === <span class="hljs-literal">true</span> || updateFlag === <span class="hljs-literal">true</span> ) {
            <span class="hljs-keyword">this</span>._assignValue( key, index );
            <span class="hljs-keyword">this</span>._updateAttributeUpdateRange( key, index );

            <span class="hljs-keyword">if</span> ( updateFlag === <span class="hljs-literal">true</span> &amp;&amp; updateCounts[ key ] === <span class="hljs-keyword">this</span>.particleCount ) {
                updateFlags[ key ] = <span class="hljs-literal">false</span>;
                updateCounts[ key ] = <span class="hljs-number">0.0</span>;
            }
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> ( updateFlag == <span class="hljs-literal">true</span> ) {
                ++updateCounts[ key ];
            }
        }
    }
};

SPE.Emitter.prototype._updateAttributeUpdateRange = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> attr, i </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> ranges = <span class="hljs-keyword">this</span>.bufferUpdateRanges[ attr ];

    ranges.min = <span class="hljs-built_in">Math</span>.min( i, ranges.min );
    ranges.max = <span class="hljs-built_in">Math</span>.max( i, ranges.max );
};

SPE.Emitter.prototype._resetBufferRanges = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">var</span> ranges = <span class="hljs-keyword">this</span>.bufferUpdateRanges,
        keys = <span class="hljs-keyword">this</span>.bufferUpdateKeys,
        i = <span class="hljs-keyword">this</span>.bufferUpdateCount - <span class="hljs-number">1</span>,
        key;

    <span class="hljs-keyword">for</span> ( i; i &gt;= <span class="hljs-number">0</span>; --i ) {
        key = keys[ i ];
        ranges[ key ].min = <span class="hljs-built_in">Number</span>.POSITIVE_INFINITY;
        ranges[ key ].max = <span class="hljs-built_in">Number</span>.NEGATIVE_INFINITY;
    }
};

SPE.Emitter.prototype._onRemove = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-138">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-138">&#182;</a>
              </div>
              <p>Reset any properties of the emitter that were set by
a group when it was added.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.particlesPerSecond = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">this</span>.attributeOffset = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">this</span>.activationIndex = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">this</span>.activeParticleCount = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">this</span>.group = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">this</span>.attributes = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">this</span>.paramsArray = <span class="hljs-literal">null</span>;
    <span class="hljs-keyword">this</span>.age = <span class="hljs-number">0.0</span>;
};

SPE.Emitter.prototype._decrementParticleCount = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;
    --<span class="hljs-keyword">this</span>.activeParticleCount;</pre></div></div>
            
        </li>
        
        
        <li id="section-139">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-139">&#182;</a>
              </div>
              <p>TODO:</p>
<ul>
<li>Trigger event if count === 0.</li>
</ul>

            </div>
            
            <div class="content"><div class='highlight'><pre>};

SPE.Emitter.prototype._incrementParticleCount = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;
    ++<span class="hljs-keyword">this</span>.activeParticleCount;</pre></div></div>
            
        </li>
        
        
        <li id="section-140">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-140">&#182;</a>
              </div>
              <p>TODO:</p>
<ul>
<li>Trigger event if count === this.particleCount.</li>
</ul>

            </div>
            
            <div class="content"><div class='highlight'><pre>};

SPE.Emitter.prototype._checkParticleAges = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> start, end, params, dt </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;
    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = end - <span class="hljs-number">1</span>, index, maxAge, age, alive; i &gt;= start; --i ) {
        index = i * <span class="hljs-number">4</span>;

        alive = params[ index ];

        <span class="hljs-keyword">if</span> ( alive === <span class="hljs-number">0.0</span> ) {
            <span class="hljs-keyword">continue</span>;
        }</pre></div></div>
            
        </li>
        
        
        <li id="section-141">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-141">&#182;</a>
              </div>
              <p>Increment age</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        age = params[ index + <span class="hljs-number">1</span> ];
        maxAge = params[ index + <span class="hljs-number">2</span> ];

        <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.direction === <span class="hljs-number">1</span> ) {
            age += dt;

            <span class="hljs-keyword">if</span> ( age &gt;= maxAge ) {
                age = <span class="hljs-number">0.0</span>;
                alive = <span class="hljs-number">0.0</span>;
                <span class="hljs-keyword">this</span>._decrementParticleCount();
            }
        }
        <span class="hljs-keyword">else</span> {
            age -= dt;

            <span class="hljs-keyword">if</span> ( age &lt;= <span class="hljs-number">0.0</span> ) {
                age = maxAge;
                alive = <span class="hljs-number">0.0</span>;
                <span class="hljs-keyword">this</span>._decrementParticleCount();
            }
        }

        params[ index ] = alive;
        params[ index + <span class="hljs-number">1</span> ] = age;

        <span class="hljs-keyword">this</span>._updateAttributeUpdateRange( <span class="hljs-string">'params'</span>, i );
    }
};

SPE.Emitter.prototype._activateParticles = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> activationStart, activationEnd, params, dtPerParticle </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;
    <span class="hljs-keyword">var</span> direction = <span class="hljs-keyword">this</span>.direction;

    <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = activationStart, index, dtValue; i &lt; activationEnd; ++i ) {
        index = i * <span class="hljs-number">4</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-142">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-142">&#182;</a>
              </div>
              <p>Don’t re-activate particles that aren’t dead yet.
if ( params[ index ] !== 0.0 &amp;&amp; ( this.particleCount !== 1 || this.activeMultiplier !== 1 ) ) {
    continue;
}</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>
        <span class="hljs-keyword">if</span> ( params[ index ] != <span class="hljs-number">0.0</span> &amp;&amp; <span class="hljs-keyword">this</span>.particleCount !== <span class="hljs-number">1</span> ) {
            <span class="hljs-keyword">continue</span>;
        }</pre></div></div>
            
        </li>
        
        
        <li id="section-143">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-143">&#182;</a>
              </div>
              <p>Increment the active particle count.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">this</span>._incrementParticleCount();</pre></div></div>
            
        </li>
        
        
        <li id="section-144">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-144">&#182;</a>
              </div>
              <p>Mark the particle as alive.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        params[ index ] = <span class="hljs-number">1.0</span>;</pre></div></div>
            
        </li>
        
        
        <li id="section-145">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-145">&#182;</a>
              </div>
              <p>Reset the particle</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        <span class="hljs-keyword">this</span>._resetParticle( i );</pre></div></div>
            
        </li>
        
        
        <li id="section-146">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-146">&#182;</a>
              </div>
              <p>Move each particle being activated to
it’s actual position in time.</p>
<p>This stops particles being ‘clumped’ together
when frame rates are on the lower side of 60fps
or not constant (a very real possibility!)</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>        dtValue = dtPerParticle * ( i - activationStart )
        params[ index + <span class="hljs-number">1</span> ] = direction === -<span class="hljs-number">1</span> ? params[ index + <span class="hljs-number">2</span> ] - dtValue : dtValue;

        <span class="hljs-keyword">this</span>._updateAttributeUpdateRange( <span class="hljs-string">'params'</span>, i );
    }
};

<span class="hljs-comment">/**
 * Simulates one frame's worth of particles, updating particles
 * that are already alive, and marking ones that are currently dead
 * but should be alive as alive.
 *
 * If the emitter is marked as static, then this function will do nothing.
 *
 * @param  {Number} dt The number of seconds to simulate (deltaTime)
 */</span>
SPE.Emitter.prototype.tick = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> dt </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.isStatic ) {
        <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.paramsArray === <span class="hljs-literal">null</span> ) {
        <span class="hljs-keyword">this</span>.paramsArray = <span class="hljs-keyword">this</span>.attributes.params.typedArray.array;
    }

    <span class="hljs-keyword">var</span> start = <span class="hljs-keyword">this</span>.attributeOffset,
        end = start + <span class="hljs-keyword">this</span>.particleCount,
        params = <span class="hljs-keyword">this</span>.paramsArray, <span class="hljs-comment">// vec3( alive, age, maxAge, wiggle )</span>
        ppsDt = <span class="hljs-keyword">this</span>.particlesPerSecond * <span class="hljs-keyword">this</span>.activeMultiplier * dt,
        activationIndex = <span class="hljs-keyword">this</span>.activationIndex;</pre></div></div>
            
        </li>
        
        
        <li id="section-147">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-147">&#182;</a>
              </div>
              <p>Reset the buffer update indices.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>._resetBufferRanges();</pre></div></div>
            
        </li>
        
        
        <li id="section-148">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-148">&#182;</a>
              </div>
              <p>Increment age for those particles that are alive,
and kill off any particles whose age is over the limit.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>._checkParticleAges( start, end, params, dt );</pre></div></div>
            
        </li>
        
        
        <li id="section-149">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-149">&#182;</a>
              </div>
              <p>If the emitter is dead, reset the age of the emitter to zero,
ready to go again if required</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.alive === <span class="hljs-literal">false</span> ) {
        <span class="hljs-keyword">this</span>.age = <span class="hljs-number">0.0</span>;
        <span class="hljs-keyword">return</span>;
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-150">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-150">&#182;</a>
              </div>
              <p>If the emitter has a specified lifetime and we’ve exceeded it,
mark the emitter as dead.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.duration !== <span class="hljs-literal">null</span> &amp;&amp; <span class="hljs-keyword">this</span>.age &gt; <span class="hljs-keyword">this</span>.duration ) {
        <span class="hljs-keyword">this</span>.alive = <span class="hljs-literal">false</span>;
        <span class="hljs-keyword">this</span>.age = <span class="hljs-number">0.0</span>;
        <span class="hljs-keyword">return</span>;
    }


    <span class="hljs-keyword">var</span> activationStart = <span class="hljs-keyword">this</span>.particleCount === <span class="hljs-number">1</span> ? activationIndex : ( activationIndex | <span class="hljs-number">0</span> ),
        activationEnd = <span class="hljs-built_in">Math</span>.min( activationStart + ppsDt, <span class="hljs-keyword">this</span>.activationEnd ),
        activationCount = activationEnd - <span class="hljs-keyword">this</span>.activationIndex | <span class="hljs-number">0</span>,
        dtPerParticle = activationCount &gt; <span class="hljs-number">0</span> ? dt / activationCount : <span class="hljs-number">0</span>;

    <span class="hljs-keyword">this</span>._activateParticles( activationStart, activationEnd, params, dtPerParticle );</pre></div></div>
            
        </li>
        
        
        <li id="section-151">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-151">&#182;</a>
              </div>
              <p>Move the activation window forward, soldier.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.activationIndex += ppsDt;

    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.activationIndex &gt; end ) {
        <span class="hljs-keyword">this</span>.activationIndex = start;
    }</pre></div></div>
            
        </li>
        
        
        <li id="section-152">
            <div class="annotation">
              
              <div class="pilwrap ">
                <a class="pilcrow" href="#section-152">&#182;</a>
              </div>
              <p>Increment the age of the emitter.</p>

            </div>
            
            <div class="content"><div class='highlight'><pre>    <span class="hljs-keyword">this</span>.age += dt;
};

<span class="hljs-comment">/**
 * Resets all the emitter's particles to their start positions
 * and marks the particles as dead if the `force` argument is
 * true.
 *
 * @param  {Boolean} [force=undefined] If true, all particles will be marked as dead instantly.
 * @return {Emitter}       This emitter instance.
 */</span>
SPE.Emitter.prototype.reset = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"> force </span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.age = <span class="hljs-number">0.0</span>;
    <span class="hljs-keyword">this</span>.alive = <span class="hljs-literal">false</span>;

    <span class="hljs-keyword">if</span> ( force === <span class="hljs-literal">true</span> ) {
        <span class="hljs-keyword">var</span> start = <span class="hljs-keyword">this</span>.attributeOffset,
            end = start + <span class="hljs-keyword">this</span>.particleCount,
            array = <span class="hljs-keyword">this</span>.paramsArray,
            attr = <span class="hljs-keyword">this</span>.attributes.params.bufferAttribute;

        <span class="hljs-keyword">for</span> ( <span class="hljs-keyword">var</span> i = end - <span class="hljs-number">1</span>, index; i &gt;= start; --i ) {
            index = i * <span class="hljs-number">4</span>;

            array[ index ] = <span class="hljs-number">0.0</span>;
            array[ index + <span class="hljs-number">1</span> ] = <span class="hljs-number">0.0</span>;
        }

        attr.updateRange.offset = <span class="hljs-number">0</span>;
        attr.updateRange.count = -<span class="hljs-number">1</span>;
        attr.needsUpdate = <span class="hljs-literal">true</span>;
    }

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};

<span class="hljs-comment">/**
 * Enables the emitter. If not already enabled, the emitter
 * will start emitting particles.
 *
 * @return {Emitter} This emitter instance.
 */</span>
SPE.Emitter.prototype.enable = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;
    <span class="hljs-keyword">this</span>.alive = <span class="hljs-literal">true</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};

<span class="hljs-comment">/**
 * Disables th emitter, but does not instantly remove it's
 * particles fromt the scene. When called, the emitter will be
 * 'switched off' and just stop emitting. Any particle's alive will
 * be allowed to finish their lifecycle.
 *
 * @return {Emitter} This emitter instance.
 */</span>
SPE.Emitter.prototype.disable = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;

    <span class="hljs-keyword">this</span>.alive = <span class="hljs-literal">false</span>;
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};

<span class="hljs-comment">/**
 * Remove this emitter from it's parent group (if it has been added to one).
 * Delgates to SPE.group.prototype.removeEmitter().
 *
 * When called, all particle's belonging to this emitter will be instantly
 * removed from the scene.
 *
 * @return {Emitter} This emitter instance.
 *
 * @see SPE.Group.prototype.removeEmitter
 */</span>
SPE.Emitter.prototype.remove = <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
<span class="hljs-pi">    'use strict'</span>;
    <span class="hljs-keyword">if</span> ( <span class="hljs-keyword">this</span>.group !== <span class="hljs-literal">null</span> ) {
        <span class="hljs-keyword">this</span>.group.removeEmitter( <span class="hljs-keyword">this</span> );
    }
    <span class="hljs-keyword">else</span> {
        <span class="hljs-built_in">console</span>.error( <span class="hljs-string">'Emitter does not belong to a group, cannot remove.'</span> );
    }

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>;
};</pre></div></div>
            
        </li>
        
    </ul>
  </div>
</body>
</html>
